node-datachannel 0.2.4 → 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 (67) hide show
  1. package/.editorconfig +12 -0
  2. package/.eslintignore +2 -0
  3. package/.eslintrc.js +8 -0
  4. package/.github/FUNDING.yml +2 -0
  5. package/.github/workflows/build-linux.yml +3 -3
  6. package/.github/workflows/build-mac.yml +1 -1
  7. package/.github/workflows/build-win.yml +4 -4
  8. package/.github/workflows/lint.yml +22 -0
  9. package/.prettierrc.js +7 -0
  10. package/CMakeLists.txt +8 -2
  11. package/README.md +4 -4
  12. package/examples/client-server/client-benchmark.js +43 -32
  13. package/examples/client-server/client-periodic.js +30 -14
  14. package/examples/client-server/client.js +6 -5
  15. package/examples/client-server/package-lock.json +183 -44
  16. package/examples/client-server/signaling-server.js +3 -5
  17. package/examples/media/media.js +9 -9
  18. package/lib/datachannel-stream.js +23 -12
  19. package/lib/index.d.ts +113 -116
  20. package/lib/index.js +3 -2
  21. package/node_modules/detect-libc/package.json +1 -0
  22. package/node_modules/lru-cache/package.json +1 -2
  23. package/node_modules/minimist/index.js +6 -2
  24. package/node_modules/minimist/package.json +10 -11
  25. package/node_modules/minimist/readme.markdown +4 -1
  26. package/node_modules/minimist/test/proto.js +16 -0
  27. package/node_modules/node-abi/node_modules/semver/README.md +3 -1
  28. package/node_modules/node-abi/node_modules/semver/bin/semver.js +19 -9
  29. package/node_modules/node-abi/node_modules/semver/classes/comparator.js +3 -2
  30. package/node_modules/node-abi/node_modules/semver/classes/index.js +1 -1
  31. package/node_modules/node-abi/node_modules/semver/classes/range.js +31 -22
  32. package/node_modules/node-abi/node_modules/semver/classes/semver.js +1 -1
  33. package/node_modules/node-abi/node_modules/semver/functions/cmp.js +8 -4
  34. package/node_modules/node-abi/node_modules/semver/functions/coerce.js +3 -2
  35. package/node_modules/node-abi/node_modules/semver/functions/inc.js +4 -1
  36. package/node_modules/node-abi/node_modules/semver/functions/parse.js +1 -1
  37. package/node_modules/node-abi/node_modules/semver/internal/constants.js +2 -2
  38. package/node_modules/node-abi/node_modules/semver/internal/identifiers.js +1 -1
  39. package/node_modules/node-abi/node_modules/semver/internal/parse-options.js +3 -3
  40. package/node_modules/node-abi/node_modules/semver/internal/re.js +3 -3
  41. package/node_modules/node-abi/node_modules/semver/package.json +51 -18
  42. package/node_modules/node-abi/node_modules/semver/ranges/min-version.js +2 -1
  43. package/node_modules/node-abi/node_modules/semver/ranges/outside.js +1 -1
  44. package/node_modules/node-abi/node_modules/semver/ranges/simplify.js +15 -12
  45. package/node_modules/node-abi/node_modules/semver/ranges/subset.js +53 -31
  46. package/node_modules/node-abi/package.json +1 -0
  47. package/node_modules/npmlog/node_modules/are-we-there-yet/package.json +10 -10
  48. package/node_modules/npmlog/package.json +1 -1
  49. package/node_modules/tar-stream/node_modules/bl/.travis.yml +4 -3
  50. package/node_modules/tar-stream/node_modules/bl/BufferList.js +1 -1
  51. package/node_modules/tar-stream/node_modules/bl/package.json +10 -10
  52. package/node_modules/tar-stream/node_modules/bl/test/test.js +20 -2
  53. package/node_modules/wide-align/LICENSE +0 -0
  54. package/node_modules/wide-align/README.md +0 -0
  55. package/node_modules/wide-align/align.js +0 -0
  56. package/node_modules/wide-align/package.json +14 -14
  57. package/package.json +12 -4
  58. package/src/data-channel-wrapper.cpp +90 -40
  59. package/src/data-channel-wrapper.h +2 -0
  60. package/src/media-audio-wrapper.cpp +5 -5
  61. package/src/media-track-wrapper.cpp +96 -38
  62. package/src/media-track-wrapper.h +1 -0
  63. package/src/media-video-wrapper.cpp +5 -5
  64. package/src/peer-connection-wrapper.cpp +111 -54
  65. package/test/connectivity.js +22 -21
  66. package/test/test.js +25 -33
  67. 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
 
@@ -147,10 +147,6 @@ PeerConnectionWrapper::PeerConnectionWrapper(const Napi::CallbackInfo &info) : N
147
147
  std::string strType = proxyServer.Get("type").As<Napi::String>().ToString();
148
148
  rtc::ProxyServer::Type type = rtc::ProxyServer::Type::Http;
149
149
 
150
- if (strType == "None")
151
- type = rtc::ProxyServer::Type::None;
152
- if (strType == "Http")
153
- type = rtc::ProxyServer::Type::Http;
154
150
  if (strType == "Socks5")
155
151
  type = rtc::ProxyServer::Type::Socks5;
156
152
 
@@ -176,6 +172,14 @@ PeerConnectionWrapper::PeerConnectionWrapper(const Napi::CallbackInfo &info) : N
176
172
  if (config.Get("enableIceTcp").IsBoolean())
177
173
  rtcConfig.enableIceTcp = config.Get("enableIceTcp").As<Napi::Boolean>();
178
174
 
175
+ // enableIceUdpMux option
176
+ if (config.Get("enableIceUdpMux").IsBoolean())
177
+ rtcConfig.enableIceUdpMux = config.Get("enableIceUdpMux").As<Napi::Boolean>();
178
+
179
+ // disableAutoNegotiation option
180
+ if (config.Get("disableAutoNegotiation").IsBoolean())
181
+ rtcConfig.disableAutoNegotiation = config.Get("disableAutoNegotiation").As<Napi::Boolean>();
182
+
179
183
  // Max Message Size
180
184
  if (config.Get("maxMessageSize").IsNumber())
181
185
  rtcConfig.maxMessageSize = config.Get("maxMessageSize").As<Napi::Number>().Uint32Value();
@@ -207,7 +211,7 @@ PeerConnectionWrapper::PeerConnectionWrapper(const Napi::CallbackInfo &info) : N
207
211
  }
208
212
  catch (std::exception &ex)
209
213
  {
210
- 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();
211
215
  return;
212
216
  }
213
217
 
@@ -221,28 +225,28 @@ PeerConnectionWrapper::~PeerConnectionWrapper()
221
225
 
222
226
  void PeerConnectionWrapper::doClose()
223
227
  {
224
- instances.erase(this);
225
-
226
228
  if (mRtcPeerConnPtr)
227
229
  {
228
230
  try
229
231
  {
230
- mOnLocalDescriptionCallback.reset();
231
- mOnLocalCandidateCallback.reset();
232
- mOnStateChangeCallback.reset();
233
- mOnGatheringStateChangeCallback.reset();
234
- mOnDataChannelCallback.reset();
235
- mOnTrackCallback.reset();
236
-
237
232
  mRtcPeerConnPtr->close();
238
233
  mRtcPeerConnPtr.reset();
239
234
  }
240
235
  catch (std::exception &ex)
241
236
  {
242
- 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;
243
238
  return;
244
239
  }
245
240
  }
241
+
242
+ mOnLocalDescriptionCallback.reset();
243
+ mOnLocalCandidateCallback.reset();
244
+ mOnStateChangeCallback.reset();
245
+ mOnGatheringStateChangeCallback.reset();
246
+ mOnDataChannelCallback.reset();
247
+ mOnTrackCallback.reset();
248
+
249
+ instances.erase(this);
246
250
  }
247
251
 
248
252
  void PeerConnectionWrapper::close(const Napi::CallbackInfo &info)
@@ -253,14 +257,14 @@ void PeerConnectionWrapper::close(const Napi::CallbackInfo &info)
253
257
  void PeerConnectionWrapper::setLocalDescription(const Napi::CallbackInfo &info)
254
258
  {
255
259
  Napi::Env env = info.Env();
260
+ int length = info.Length();
261
+
256
262
  if (!mRtcPeerConnPtr)
257
263
  {
258
- Napi::Error::New(info.Env(), "It seems peer-connection is closed").ThrowAsJavaScriptException();
264
+ Napi::Error::New(env, "setLocalDescription() called on destroyed peer connection").ThrowAsJavaScriptException();
259
265
  return;
260
266
  }
261
267
 
262
- int length = info.Length();
263
-
264
268
  rtc::Description::Type type = rtc::Description::Type::Unspec;
265
269
 
266
270
  // optional
@@ -289,13 +293,14 @@ void PeerConnectionWrapper::setLocalDescription(const Napi::CallbackInfo &info)
289
293
  void PeerConnectionWrapper::setRemoteDescription(const Napi::CallbackInfo &info)
290
294
  {
291
295
  Napi::Env env = info.Env();
296
+ int length = info.Length();
297
+
292
298
  if (!mRtcPeerConnPtr)
293
299
  {
294
- Napi::Error::New(info.Env(), "It seems peer-connection is closed").ThrowAsJavaScriptException();
300
+ Napi::Error::New(env, "setRemoteDescription() called on destroyed peer connection").ThrowAsJavaScriptException();
295
301
  return;
296
302
  }
297
303
 
298
- int length = info.Length();
299
304
  if (length < 2 || !info[0].IsString() || !info[1].IsString())
300
305
  {
301
306
  Napi::TypeError::New(info.Env(), "String,String expected").ThrowAsJavaScriptException();
@@ -312,7 +317,7 @@ void PeerConnectionWrapper::setRemoteDescription(const Napi::CallbackInfo &info)
312
317
  }
313
318
  catch (std::exception &ex)
314
319
  {
315
- 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();
316
321
  return;
317
322
  }
318
323
  }
@@ -320,7 +325,13 @@ void PeerConnectionWrapper::setRemoteDescription(const Napi::CallbackInfo &info)
320
325
  Napi::Value PeerConnectionWrapper::localDescription(const Napi::CallbackInfo &info)
321
326
  {
322
327
  Napi::Env env = info.Env();
323
- 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
+ }
324
335
 
325
336
  Napi::Object obj = Napi::Object::New(env);
326
337
  obj.Set("type", desc->typeString());
@@ -331,16 +342,17 @@ Napi::Value PeerConnectionWrapper::localDescription(const Napi::CallbackInfo &in
331
342
  void PeerConnectionWrapper::addRemoteCandidate(const Napi::CallbackInfo &info)
332
343
  {
333
344
  Napi::Env env = info.Env();
345
+ int length = info.Length();
346
+
334
347
  if (!mRtcPeerConnPtr)
335
348
  {
336
- Napi::Error::New(info.Env(), "It seems peer-connection is closed").ThrowAsJavaScriptException();
349
+ Napi::Error::New(env, "addRemoteCandidate() called on destroyed peer connection").ThrowAsJavaScriptException();
337
350
  return;
338
351
  }
339
352
 
340
- int length = info.Length();
341
353
  if (length < 2 || !info[0].IsString() || !info[1].IsString())
342
354
  {
343
- Napi::TypeError::New(info.Env(), "String,String expected").ThrowAsJavaScriptException();
355
+ Napi::TypeError::New(info.Env(), "String, String expected").ThrowAsJavaScriptException();
344
356
  return;
345
357
  }
346
358
 
@@ -352,22 +364,22 @@ void PeerConnectionWrapper::addRemoteCandidate(const Napi::CallbackInfo &info)
352
364
  }
353
365
  catch (std::exception &ex)
354
366
  {
355
- 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();
356
368
  return;
357
369
  }
358
370
  }
359
371
 
360
372
  Napi::Value PeerConnectionWrapper::createDataChannel(const Napi::CallbackInfo &info)
361
373
  {
374
+ Napi::Env env = info.Env();
375
+ int length = info.Length();
376
+
362
377
  if (!mRtcPeerConnPtr)
363
378
  {
364
- Napi::Error::New(info.Env(), "It seems peer-connection is closed").ThrowAsJavaScriptException();
379
+ Napi::Error::New(env, "createDataChannel() called on destroyed peer connection").ThrowAsJavaScriptException();
365
380
  return info.Env().Null();
366
381
  }
367
382
 
368
- Napi::Env env = info.Env();
369
- int length = info.Length();
370
-
371
383
  if (length < 1 || !info[0].IsString())
372
384
  {
373
385
  Napi::TypeError::New(env, "Data Channel Label expected").ThrowAsJavaScriptException();
@@ -521,7 +533,7 @@ Napi::Value PeerConnectionWrapper::createDataChannel(const Napi::CallbackInfo &i
521
533
  }
522
534
  catch (std::exception &ex)
523
535
  {
524
- 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();
525
537
  return info.Env().Null();
526
538
  }
527
539
  }
@@ -531,6 +543,12 @@ void PeerConnectionWrapper::onLocalDescription(const Napi::CallbackInfo &info)
531
543
  Napi::Env env = info.Env();
532
544
  int length = info.Length();
533
545
 
546
+ if (!mRtcPeerConnPtr)
547
+ {
548
+ Napi::Error::New(env, "onLocalDescription() called on destroyed peer connection").ThrowAsJavaScriptException();
549
+ return;
550
+ }
551
+
534
552
  if (length < 1 || !info[0].IsFunction())
535
553
  {
536
554
  Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
@@ -540,9 +558,9 @@ void PeerConnectionWrapper::onLocalDescription(const Napi::CallbackInfo &info)
540
558
  // Callback
541
559
  mOnLocalDescriptionCallback = std::make_unique<ThreadSafeCallback>(info[0].As<Napi::Function>());
542
560
 
543
- mRtcPeerConnPtr->onLocalDescription([&](const rtc::Description &sdp) {
561
+ mRtcPeerConnPtr->onLocalDescription([&](rtc::Description sdp) {
544
562
  if (mOnLocalDescriptionCallback)
545
- 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) {
546
564
  // Check the peer connection is not closed
547
565
  if(instances.find(this) == instances.end())
548
566
  throw ThreadSafeCallback::CancelException();
@@ -560,6 +578,12 @@ void PeerConnectionWrapper::onLocalCandidate(const Napi::CallbackInfo &info)
560
578
  Napi::Env env = info.Env();
561
579
  int length = info.Length();
562
580
 
581
+ if (!mRtcPeerConnPtr)
582
+ {
583
+ Napi::Error::New(env, "onLocalCandidate() called on destroyed peer connection").ThrowAsJavaScriptException();
584
+ return;
585
+ }
586
+
563
587
  if (length < 1 || !info[0].IsFunction())
564
588
  {
565
589
  Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
@@ -569,9 +593,9 @@ void PeerConnectionWrapper::onLocalCandidate(const Napi::CallbackInfo &info)
569
593
  // Callback
570
594
  mOnLocalCandidateCallback = std::make_unique<ThreadSafeCallback>(info[0].As<Napi::Function>());
571
595
 
572
- mRtcPeerConnPtr->onLocalCandidate([&](const rtc::Candidate &candidate) {
596
+ mRtcPeerConnPtr->onLocalCandidate([&](rtc::Candidate cand) {
573
597
  if (mOnLocalCandidateCallback)
574
- 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) {
575
599
  // Check the peer connection is not closed
576
600
  if(instances.find(this) == instances.end())
577
601
  throw ThreadSafeCallback::CancelException();
@@ -579,8 +603,8 @@ void PeerConnectionWrapper::onLocalCandidate(const Napi::CallbackInfo &info)
579
603
  // This will run in main thread and needs to construct the
580
604
  // arguments for the call
581
605
  args = {
582
- Napi::String::New(env, std::string(candidate)),
583
- Napi::String::New(env, candidate.mid())};
606
+ Napi::String::New(env, std::string(cand)),
607
+ Napi::String::New(env, cand.mid())};
584
608
  }); });
585
609
  }
586
610
 
@@ -589,6 +613,12 @@ void PeerConnectionWrapper::onStateChange(const Napi::CallbackInfo &info)
589
613
  Napi::Env env = info.Env();
590
614
  int length = info.Length();
591
615
 
616
+ if (!mRtcPeerConnPtr)
617
+ {
618
+ Napi::Error::New(env, "onStateChange() called on destroyed peer connection").ThrowAsJavaScriptException();
619
+ return;
620
+ }
621
+
592
622
  if (length < 1 || !info[0].IsFunction())
593
623
  {
594
624
  Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
@@ -601,8 +631,8 @@ void PeerConnectionWrapper::onStateChange(const Napi::CallbackInfo &info)
601
631
  mRtcPeerConnPtr->onStateChange([&](rtc::PeerConnection::State state) {
602
632
  if (mOnStateChangeCallback)
603
633
  mOnStateChangeCallback->call([this, state](Napi::Env env, std::vector<napi_value> &args) {
604
- // Check the peer connection is not closed
605
- if(instances.find(this) == instances.end())
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())
606
636
  throw ThreadSafeCallback::CancelException();
607
637
 
608
638
  // This will run in main thread and needs to construct the
@@ -618,6 +648,12 @@ void PeerConnectionWrapper::onSignalingStateChange(const Napi::CallbackInfo &inf
618
648
  Napi::Env env = info.Env();
619
649
  int length = info.Length();
620
650
 
651
+ if (!mRtcPeerConnPtr)
652
+ {
653
+ Napi::Error::New(env, "onSignalingStateChange() called on destroyed peer connection").ThrowAsJavaScriptException();
654
+ return;
655
+ }
656
+
621
657
  if (length < 1 || !info[0].IsFunction())
622
658
  {
623
659
  Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
@@ -647,6 +683,12 @@ void PeerConnectionWrapper::onGatheringStateChange(const Napi::CallbackInfo &inf
647
683
  Napi::Env env = info.Env();
648
684
  int length = info.Length();
649
685
 
686
+ if (!mRtcPeerConnPtr)
687
+ {
688
+ Napi::Error::New(env, "onGatheringStateChange() called on destroyed peer connection").ThrowAsJavaScriptException();
689
+ return;
690
+ }
691
+
650
692
  if (length < 1 || !info[0].IsFunction())
651
693
  {
652
694
  Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
@@ -676,6 +718,12 @@ void PeerConnectionWrapper::onDataChannel(const Napi::CallbackInfo &info)
676
718
  Napi::Env env = info.Env();
677
719
  int length = info.Length();
678
720
 
721
+ if (!mRtcPeerConnPtr)
722
+ {
723
+ Napi::Error::New(env, "onDataChannel() called on destroyed peer connection").ThrowAsJavaScriptException();
724
+ return;
725
+ }
726
+
679
727
  if (length < 1 || !info[0].IsFunction())
680
728
  {
681
729
  Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
@@ -704,6 +752,7 @@ void PeerConnectionWrapper::onDataChannel(const Napi::CallbackInfo &info)
704
752
  Napi::Value PeerConnectionWrapper::bytesSent(const Napi::CallbackInfo &info)
705
753
  {
706
754
  Napi::Env env = info.Env();
755
+
707
756
  if (!mRtcPeerConnPtr)
708
757
  {
709
758
  return Napi::Number::New(info.Env(), 0);
@@ -715,7 +764,7 @@ Napi::Value PeerConnectionWrapper::bytesSent(const Napi::CallbackInfo &info)
715
764
  }
716
765
  catch (std::exception &ex)
717
766
  {
718
- Napi::Error::New(env, std::string("libdatachannel error# ") + ex.what()).ThrowAsJavaScriptException();
767
+ Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
719
768
  return Napi::Number::New(info.Env(), 0);
720
769
  }
721
770
  }
@@ -723,6 +772,7 @@ Napi::Value PeerConnectionWrapper::bytesSent(const Napi::CallbackInfo &info)
723
772
  Napi::Value PeerConnectionWrapper::bytesReceived(const Napi::CallbackInfo &info)
724
773
  {
725
774
  Napi::Env env = info.Env();
775
+
726
776
  if (!mRtcPeerConnPtr)
727
777
  {
728
778
  return Napi::Number::New(info.Env(), 0);
@@ -734,7 +784,7 @@ Napi::Value PeerConnectionWrapper::bytesReceived(const Napi::CallbackInfo &info)
734
784
  }
735
785
  catch (std::exception &ex)
736
786
  {
737
- Napi::Error::New(env, std::string("libdatachannel error# ") + ex.what()).ThrowAsJavaScriptException();
787
+ Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
738
788
  return Napi::Number::New(info.Env(), 0);
739
789
  }
740
790
  }
@@ -742,6 +792,7 @@ Napi::Value PeerConnectionWrapper::bytesReceived(const Napi::CallbackInfo &info)
742
792
  Napi::Value PeerConnectionWrapper::rtt(const Napi::CallbackInfo &info)
743
793
  {
744
794
  Napi::Env env = info.Env();
795
+
745
796
  if (!mRtcPeerConnPtr)
746
797
  {
747
798
  return Napi::Number::New(info.Env(), 0);
@@ -753,7 +804,7 @@ Napi::Value PeerConnectionWrapper::rtt(const Napi::CallbackInfo &info)
753
804
  }
754
805
  catch (std::exception &ex)
755
806
  {
756
- Napi::Error::New(env, std::string("libdatachannel error# ") + ex.what()).ThrowAsJavaScriptException();
807
+ Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
757
808
  return Napi::Number::New(info.Env(), -1);
758
809
  }
759
810
  }
@@ -761,16 +812,17 @@ Napi::Value PeerConnectionWrapper::rtt(const Napi::CallbackInfo &info)
761
812
  Napi::Value PeerConnectionWrapper::getSelectedCandidatePair(const Napi::CallbackInfo &info)
762
813
  {
763
814
  Napi::Env env = info.Env();
815
+
764
816
  if (!mRtcPeerConnPtr)
765
817
  {
766
- return Napi::Number::New(info.Env(), 0);
818
+ return env.Null();
767
819
  }
768
820
 
769
821
  try
770
822
  {
771
823
  rtc::Candidate local, remote;
772
824
  if (!mRtcPeerConnPtr->getSelectedCandidatePair(&local, &remote))
773
- return info.Env().Null();
825
+ return env.Null();
774
826
 
775
827
  Napi::Object retvalue = Napi::Object::New(env);
776
828
  Napi::Object localObj = Napi::Object::New(env);
@@ -793,7 +845,7 @@ Napi::Value PeerConnectionWrapper::getSelectedCandidatePair(const Napi::Callback
793
845
  }
794
846
  catch (std::exception &ex)
795
847
  {
796
- Napi::Error::New(env, std::string("libdatachannel error# ") + ex.what()).ThrowAsJavaScriptException();
848
+ Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
797
849
  return Napi::Number::New(info.Env(), -1);
798
850
  }
799
851
  }
@@ -841,7 +893,7 @@ Napi::Value PeerConnectionWrapper::addTrack(const Napi::CallbackInfo &info)
841
893
 
842
894
  if (!mRtcPeerConnPtr)
843
895
  {
844
- Napi::Error::New(info.Env(), "It seems peer-connection is closed").ThrowAsJavaScriptException();
896
+ Napi::Error::New(env, "addTrack() called on destroyed peer connection").ThrowAsJavaScriptException();
845
897
  return env.Null();
846
898
  }
847
899
 
@@ -875,7 +927,7 @@ Napi::Value PeerConnectionWrapper::addTrack(const Napi::CallbackInfo &info)
875
927
  }
876
928
  catch (std::exception &ex)
877
929
  {
878
- Napi::Error::New(env, std::string("libdatachannel error# ") + ex.what()).ThrowAsJavaScriptException();
930
+ Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
879
931
  return env.Null();
880
932
  }
881
933
  }
@@ -885,6 +937,12 @@ void PeerConnectionWrapper::onTrack(const Napi::CallbackInfo &info)
885
937
  Napi::Env env = info.Env();
886
938
  int length = info.Length();
887
939
 
940
+ if (!mRtcPeerConnPtr)
941
+ {
942
+ Napi::Error::New(env, "onGatheringStateChange() called on destroyed peer connection").ThrowAsJavaScriptException();
943
+ return;
944
+ }
945
+
888
946
  if (length < 1 || !info[0].IsFunction())
889
947
  {
890
948
  Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
@@ -894,8 +952,7 @@ void PeerConnectionWrapper::onTrack(const Napi::CallbackInfo &info)
894
952
  // Callback
895
953
  mOnTrackCallback = std::make_unique<ThreadSafeCallback>(info[0].As<Napi::Function>());
896
954
 
897
- mRtcPeerConnPtr->onTrack([&](std::shared_ptr<rtc::Track> track)
898
- {
955
+ mRtcPeerConnPtr->onTrack([&](std::shared_ptr<rtc::Track> track) {
899
956
  if (mOnTrackCallback)
900
957
  mOnTrackCallback->call([this, track](Napi::Env env, std::vector<napi_value> &args) {
901
958
  // Check the peer connection is not closed
@@ -913,14 +970,14 @@ void PeerConnectionWrapper::onTrack(const Napi::CallbackInfo &info)
913
970
  Napi::Value PeerConnectionWrapper::hasMedia(const Napi::CallbackInfo &info)
914
971
  {
915
972
  Napi::Env env = info.Env();
916
- return Napi::Boolean::New(env, mRtcPeerConnPtr->hasMedia());
973
+ return Napi::Boolean::New(env, mRtcPeerConnPtr ? mRtcPeerConnPtr->hasMedia() : false);
917
974
  }
918
975
 
919
976
  Napi::Value PeerConnectionWrapper::state(const Napi::CallbackInfo &info)
920
977
  {
921
978
  Napi::Env env = info.Env();
922
979
  std::ostringstream stream;
923
- stream << mRtcPeerConnPtr->state();
980
+ stream << (mRtcPeerConnPtr ? mRtcPeerConnPtr->state() : rtc::PeerConnection::State::Closed);
924
981
  return Napi::String::New(env, stream.str());
925
982
  }
926
983
 
@@ -928,7 +985,7 @@ Napi::Value PeerConnectionWrapper::signalingState(const Napi::CallbackInfo &info
928
985
  {
929
986
  Napi::Env env = info.Env();
930
987
  std::ostringstream stream;
931
- stream << mRtcPeerConnPtr->signalingState();
988
+ stream << (mRtcPeerConnPtr ? mRtcPeerConnPtr->signalingState() : rtc::PeerConnection::SignalingState::Stable);
932
989
  return Napi::String::New(env, stream.str());
933
990
  }
934
991
 
@@ -936,6 +993,6 @@ Napi::Value PeerConnectionWrapper::gatheringState(const Napi::CallbackInfo &info
936
993
  {
937
994
  Napi::Env env = info.Env();
938
995
  std::ostringstream stream;
939
- stream << mRtcPeerConnPtr->gatheringState();
996
+ stream << (mRtcPeerConnPtr ? mRtcPeerConnPtr->gatheringState() : rtc::PeerConnection::GatheringState::Complete);
940
997
  return Napi::String::New(env, stream.str());
941
998
  }
@@ -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,48 +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');
70
+ dc2.onClosed(() => {
71
+ console.log('dc2 closed');
72
+ });
69
73
  });
70
74
 
71
75
  // DataChannel Options
@@ -77,25 +81,22 @@ peer2.onDataChannel((dc) => {
77
81
  // maxPacketLifeTime?: number;
78
82
  // maxRetransmits?: number;
79
83
  // }
80
- dc1 = peer1.createDataChannel("test");
84
+ dc1 = peer1.createDataChannel('test');
81
85
  dc1.onOpen(() => {
82
- dc1.sendMessage("Hello from Peer1");
86
+ dc1.sendMessage('Hello from Peer1');
83
87
  // Binary message: Use sendMessageBinary(Buffer)
84
88
  });
85
89
  dc1.onMessage((msg) => {
86
90
  console.log('Peer1 Received Msg:', msg);
87
91
  });
92
+ dc1.onClosed(() => {
93
+ console.log('dc1 closed');
94
+ });
88
95
 
89
96
  setTimeout(() => {
90
97
  dc1.close();
91
98
  dc2.close();
92
99
  peer1.close();
93
100
  peer2.close();
94
- dc1 = null;
95
- dc2 = null;
96
- peer1 = null;
97
- peer2 = null;
98
101
  nodeDataChannel.cleanup();
99
- // No need for this (>= V0.1.14)
100
- // process.exit();
101
102
  }, 5 * 1000);