node-datachannel 0.6.0 → 0.8.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.
@@ -0,0 +1,37 @@
1
+ import RTCCertificate from './RTCCertificate.js';
2
+ import RTCDataChannel from './RTCDataChannel.js';
3
+ import RTCDtlsTransport from './RTCDtlsTransport.js';
4
+ import RTCIceCandidate from './RTCIceCandidate.js';
5
+ import RTCIceTransport from './RTCIceTransport.js';
6
+ import RTCPeerConnection from './RTCPeerConnection.js';
7
+ import RTCSctpTransport from './RTCSctpTransport.js';
8
+ import RTCSessionDescription from './RTCSessionDescription.js';
9
+ import { RTCDataChannelEvent, RTCPeerConnectionIceEvent } from './Events.js';
10
+
11
+ export {
12
+ RTCCertificate,
13
+ RTCDataChannel,
14
+ RTCDtlsTransport,
15
+ RTCIceCandidate,
16
+ RTCIceTransport,
17
+ RTCPeerConnection,
18
+ RTCSctpTransport,
19
+ RTCSessionDescription,
20
+ RTCDataChannelEvent,
21
+ RTCPeerConnectionIceEvent,
22
+ };
23
+
24
+ declare const _default: {
25
+ RTCCertificate: typeof RTCCertificate;
26
+ RTCDataChannel: typeof RTCDataChannel;
27
+ RTCDtlsTransport: typeof RTCDtlsTransport;
28
+ RTCIceCandidate: typeof RTCIceCandidate;
29
+ RTCIceTransport: typeof RTCIceTransport;
30
+ RTCPeerConnection: typeof RTCPeerConnection;
31
+ RTCSctpTransport: typeof RTCSctpTransport;
32
+ RTCSessionDescription: typeof RTCSessionDescription;
33
+ RTCDataChannelEvent: typeof RTCDataChannelEvent;
34
+ RTCPeerConnectionIceEvent: typeof RTCPeerConnectionIceEvent;
35
+ };
36
+
37
+ export default _default;
@@ -13,6 +13,14 @@ void DataChannelWrapper::CloseAll()
13
13
  inst->doClose();
14
14
  }
15
15
 
16
+ void DataChannelWrapper::CleanupAll()
17
+ {
18
+ PLOG_DEBUG << "CleanupAll() called";
19
+ auto copy(instances);
20
+ for (auto inst : copy)
21
+ inst->doCleanup();
22
+ }
23
+
16
24
  Napi::Object DataChannelWrapper::Init(Napi::Env env, Napi::Object exports)
17
25
  {
18
26
  Napi::HandleScope scope(env);
@@ -78,11 +86,15 @@ void DataChannelWrapper::doClose()
78
86
  }
79
87
 
80
88
  mOnOpenCallback.reset();
81
- mOnClosedCallback.reset();
82
89
  mOnErrorCallback.reset();
83
90
  mOnBufferedAmountLowCallback.reset();
84
91
  mOnMessageCallback.reset();
92
+ }
85
93
 
94
+ void DataChannelWrapper::doCleanup()
95
+ {
96
+ PLOG_DEBUG << "doCleanup() called";
97
+ mOnClosedCallback.reset();
86
98
  instances.erase(this);
87
99
  }
88
100
 
@@ -350,6 +362,8 @@ void DataChannelWrapper::onClosed(const Napi::CallbackInfo &info)
350
362
  // This will run in main thread and needs to construct the
351
363
  // arguments for the call
352
364
  args = {};
365
+ },[this]{
366
+ doCleanup();
353
367
  }); });
354
368
  }
355
369
 
@@ -42,10 +42,14 @@ public:
42
42
  // Close all existing DataChannels
43
43
  static void CloseAll();
44
44
 
45
+ // Reset all Callbacks for existing DataChannels
46
+ static void CleanupAll();
47
+
45
48
  private:
46
- static std::unordered_set<DataChannelWrapper*> instances;
49
+ static std::unordered_set<DataChannelWrapper *> instances;
47
50
 
48
51
  void doClose();
52
+ void doCleanup();
49
53
 
50
54
  std::string mLabel;
51
55
  std::shared_ptr<rtc::DataChannel> mDataChannelPtr = nullptr;
@@ -2,6 +2,8 @@
2
2
  #include "media-direction.h"
3
3
  #include "media-rtcpreceivingsession-wrapper.h"
4
4
 
5
+ #include "plog/Log.h"
6
+
5
7
  Napi::FunctionReference TrackWrapper::constructor;
6
8
  std::unordered_set<TrackWrapper *> TrackWrapper::instances;
7
9
 
@@ -12,6 +14,14 @@ void TrackWrapper::CloseAll()
12
14
  inst->doClose();
13
15
  }
14
16
 
17
+ void TrackWrapper::CleanupAll()
18
+ {
19
+ PLOG_DEBUG << "CleanupAll() called";
20
+ auto copy(instances);
21
+ for (auto inst : copy)
22
+ inst->doCleanup();
23
+ }
24
+
15
25
  Napi::Object TrackWrapper::Init(Napi::Env env, Napi::Object exports)
16
26
  {
17
27
  Napi::HandleScope scope(env);
@@ -73,10 +83,14 @@ void TrackWrapper::doClose()
73
83
  }
74
84
 
75
85
  mOnOpenCallback.reset();
76
- mOnClosedCallback.reset();
77
86
  mOnErrorCallback.reset();
78
87
  mOnMessageCallback.reset();
88
+ }
79
89
 
90
+ void TrackWrapper::doCleanup()
91
+ {
92
+ PLOG_DEBUG << "doCleanup() called";
93
+ mOnClosedCallback.reset();
80
94
  instances.erase(this);
81
95
  }
82
96
 
@@ -276,7 +290,8 @@ void TrackWrapper::onOpen(const Napi::CallbackInfo &info)
276
290
  // Callback
277
291
  mOnOpenCallback = std::make_unique<ThreadSafeCallback>(info[0].As<Napi::Function>());
278
292
 
279
- mTrackPtr->onOpen([&]() {
293
+ mTrackPtr->onOpen([&]()
294
+ {
280
295
  if (mOnOpenCallback)
281
296
  mOnOpenCallback->call([this](Napi::Env env, std::vector<napi_value> &args) {
282
297
  // Check the track is not closed
@@ -309,7 +324,8 @@ void TrackWrapper::onClosed(const Napi::CallbackInfo &info)
309
324
  // Callback
310
325
  mOnClosedCallback = std::make_unique<ThreadSafeCallback>(info[0].As<Napi::Function>());
311
326
 
312
- mTrackPtr->onClosed([&]() {
327
+ mTrackPtr->onClosed([&]()
328
+ {
313
329
  if (mOnClosedCallback)
314
330
  mOnClosedCallback->call([this](Napi::Env env, std::vector<napi_value> &args) {
315
331
  // Do not check if the data channel has been closed here
@@ -317,6 +333,8 @@ void TrackWrapper::onClosed(const Napi::CallbackInfo &info)
317
333
  // This will run in main thread and needs to construct the
318
334
  // arguments for the call
319
335
  args = {};
336
+ },[this]{
337
+ doCleanup();
320
338
  }); });
321
339
  }
322
340
 
@@ -340,7 +358,8 @@ void TrackWrapper::onError(const Napi::CallbackInfo &info)
340
358
  // Callback
341
359
  mOnErrorCallback = std::make_unique<ThreadSafeCallback>(info[0].As<Napi::Function>());
342
360
 
343
- mTrackPtr->onError([&](const std::string &error) {
361
+ mTrackPtr->onError([&](const std::string &error)
362
+ {
344
363
  if (mOnErrorCallback)
345
364
  mOnErrorCallback->call([this, error](Napi::Env env, std::vector<napi_value> &args) {
346
365
  // Check the track is not closed
@@ -373,7 +392,8 @@ void TrackWrapper::onMessage(const Napi::CallbackInfo &info)
373
392
  // Callback
374
393
  mOnMessageCallback = std::make_unique<ThreadSafeCallback>(info[0].As<Napi::Function>());
375
394
 
376
- mTrackPtr->onMessage([&](std::variant<rtc::binary, std::string> message) {
395
+ mTrackPtr->onMessage([&](std::variant<rtc::binary, std::string> message)
396
+ {
377
397
  if (mOnMessageCallback)
378
398
  mOnMessageCallback->call([this, message = std::move(message)](Napi::Env env, std::vector<napi_value> &args) {
379
399
  // Check the track is not closed
@@ -39,21 +39,25 @@ public:
39
39
  void onError(const Napi::CallbackInfo &info);
40
40
  void onMessage(const Napi::CallbackInfo &info);
41
41
 
42
- // Close all existing track
42
+ // Close all existing tracks
43
43
  static void CloseAll();
44
44
 
45
+ // Reset all Callbacks for existing tracks
46
+ static void CleanupAll();
47
+
45
48
  private:
46
49
  static std::unordered_set<TrackWrapper *> instances;
47
50
 
48
51
  void doClose();
52
+ void doCleanup();
49
53
 
50
54
  std::shared_ptr<rtc::Track> mTrackPtr = nullptr;
51
55
 
52
- // Callback Ptrs
56
+ // Callback Ptrs
53
57
  std::unique_ptr<ThreadSafeCallback> mOnOpenCallback = nullptr;
54
58
  std::unique_ptr<ThreadSafeCallback> mOnClosedCallback = nullptr;
55
59
  std::unique_ptr<ThreadSafeCallback> mOnErrorCallback = nullptr;
56
60
  std::unique_ptr<ThreadSafeCallback> mOnMessageCallback = nullptr;
57
61
  };
58
62
 
59
- #endif // MEDIA_TRACK_WRAPPER_H
63
+ #endif // MEDIA_TRACK_WRAPPER_H
@@ -20,12 +20,12 @@ void PeerConnectionWrapper::CloseAll()
20
20
  inst->doClose();
21
21
  }
22
22
 
23
- void PeerConnectionWrapper::ResetCallbacksAll()
23
+ void PeerConnectionWrapper::CleanupAll()
24
24
  {
25
- PLOG_DEBUG << "ResetCallbacksAll() called";
25
+ PLOG_DEBUG << "CleanupAll() called";
26
26
  auto copy(instances);
27
27
  for (auto inst : copy)
28
- inst->doResetCallbacks();
28
+ inst->doCleanup();
29
29
  }
30
30
 
31
31
  Napi::Object PeerConnectionWrapper::Init(Napi::Env env, Napi::Object exports)
@@ -37,7 +37,6 @@ Napi::Object PeerConnectionWrapper::Init(Napi::Env env, Napi::Object exports)
37
37
  "PeerConnection",
38
38
  {
39
39
  InstanceMethod("close", &PeerConnectionWrapper::close),
40
- InstanceMethod("destroy", &PeerConnectionWrapper::destroy),
41
40
  InstanceMethod("setLocalDescription", &PeerConnectionWrapper::setLocalDescription),
42
41
  InstanceMethod("setRemoteDescription", &PeerConnectionWrapper::setRemoteDescription),
43
42
  InstanceMethod("localDescription", &PeerConnectionWrapper::localDescription),
@@ -253,7 +252,8 @@ PeerConnectionWrapper::PeerConnectionWrapper(const Napi::CallbackInfo &info) : N
253
252
  PeerConnectionWrapper::~PeerConnectionWrapper()
254
253
  {
255
254
  PLOG_DEBUG << "Destructor called";
256
- doDestroy();
255
+ doCleanup();
256
+ doClose();
257
257
  }
258
258
 
259
259
  void PeerConnectionWrapper::doClose()
@@ -273,40 +273,27 @@ void PeerConnectionWrapper::doClose()
273
273
  return;
274
274
  }
275
275
  }
276
- }
277
-
278
- void PeerConnectionWrapper::close(const Napi::CallbackInfo &info)
279
- {
280
- PLOG_DEBUG << "close() called";
281
- doClose();
282
- }
283
-
284
- void PeerConnectionWrapper::doDestroy()
285
- {
286
- PLOG_DEBUG << "doDestroy() called";
287
- doClose();
288
- doResetCallbacks();
289
- }
290
276
 
291
- void PeerConnectionWrapper::doResetCallbacks()
292
- {
293
- PLOG_DEBUG << "doResetCallbacks() called";
294
277
  mOnLocalDescriptionCallback.reset();
295
278
  mOnLocalCandidateCallback.reset();
296
- mOnStateChangeCallback.reset();
297
279
  mOnIceStateChangeCallback.reset();
298
280
  mOnSignalingStateChangeCallback.reset();
299
281
  mOnGatheringStateChangeCallback.reset();
300
282
  mOnDataChannelCallback.reset();
301
283
  mOnTrackCallback.reset();
284
+ }
302
285
 
303
- instances.erase(this);
286
+ void PeerConnectionWrapper::close(const Napi::CallbackInfo &info)
287
+ {
288
+ PLOG_DEBUG << "close() called";
289
+ doClose();
304
290
  }
305
291
 
306
- void PeerConnectionWrapper::destroy(const Napi::CallbackInfo &info)
292
+ void PeerConnectionWrapper::doCleanup()
307
293
  {
308
- PLOG_DEBUG << "destroy() called";
309
- doDestroy();
294
+ PLOG_DEBUG << "doCleanup() called";
295
+ mOnStateChangeCallback.reset();
296
+ instances.erase(this);
310
297
  }
311
298
 
312
299
  void PeerConnectionWrapper::setLocalDescription(const Napi::CallbackInfo &info)
@@ -738,6 +725,13 @@ void PeerConnectionWrapper::onStateChange(const Napi::CallbackInfo &info)
738
725
  stream << state;
739
726
  args = {Napi::String::New(env, stream.str())};
740
727
  PLOG_DEBUG << "mOnStateChangeCallback call(2)";
728
+ },[this,state](){
729
+ PLOG_DEBUG << "mOnStateChangeCallback cleanup";
730
+ // Special case for closed state, we need to reset all callbacks
731
+ if(state == rtc::PeerConnection::State::Closed)
732
+ {
733
+ doCleanup();
734
+ }
741
735
  }); });
742
736
  }
743
737
 
@@ -19,8 +19,6 @@ public:
19
19
  PeerConnectionWrapper(const Napi::CallbackInfo &info);
20
20
  ~PeerConnectionWrapper();
21
21
 
22
- void destroy(const Napi::CallbackInfo &info);
23
-
24
22
  // Functions
25
23
  void close(const Napi::CallbackInfo &info);
26
24
  void setLocalDescription(const Napi::CallbackInfo &info);
@@ -58,15 +56,14 @@ public:
58
56
  static void CloseAll();
59
57
 
60
58
  // Reset all Callbacks for existing Peer Connections
61
- static void ResetCallbacksAll();
59
+ static void CleanupAll();
62
60
 
63
61
  private:
64
62
  static Napi::FunctionReference constructor;
65
63
  static std::unordered_set<PeerConnectionWrapper *> instances;
66
64
 
67
65
  void doClose();
68
- void doDestroy();
69
- void doResetCallbacks();
66
+ void doCleanup();
70
67
 
71
68
  std::string mPeerName;
72
69
  std::unique_ptr<rtc::PeerConnection> mRtcPeerConnPtr = nullptr;
@@ -125,8 +125,11 @@ void RtcWrapper::cleanup(const Napi::CallbackInfo &info)
125
125
  if (rtc::Cleanup().wait_for(std::chrono::seconds(timeout)) == std::future_status::timeout)
126
126
  throw std::runtime_error("cleanup timeout (possible deadlock)");
127
127
 
128
- // Clear Callbacks
129
- PeerConnectionWrapper::ResetCallbacksAll();
128
+ // Cleanup the instances
129
+ PeerConnectionWrapper::CleanupAll();
130
+ DataChannelWrapper::CleanupAll();
131
+ TrackWrapper::CleanupAll();
132
+ WebSocketWrapper::CleanupAll();
130
133
 
131
134
  if (logCallback)
132
135
  logCallback.reset();
@@ -26,9 +26,9 @@ ThreadSafeCallback::~ThreadSafeCallback()
26
26
  tsfn.Abort();
27
27
  }
28
28
 
29
- void ThreadSafeCallback::call(arg_func_t argFunc)
29
+ void ThreadSafeCallback::call(arg_func_t argFunc, cleanup_func_t cleanupFunc)
30
30
  {
31
- CallbackData *data = new CallbackData{std::move(argFunc)};
31
+ CallbackData *data = new CallbackData{std::move(argFunc), std::move(cleanupFunc)};
32
32
  if (tsfn.BlockingCall(data) != napi_ok)
33
33
  {
34
34
  delete data;
@@ -47,6 +47,7 @@ void ThreadSafeCallback::callbackFunc(Napi::Env env,
47
47
 
48
48
  arg_vector_t args;
49
49
  arg_func_t argFunc(std::move(data->argFunc));
50
+ cleanup_func_t cleanup(std::move(data->cleanupFunc));
50
51
  delete data;
51
52
 
52
53
  try
@@ -59,5 +60,8 @@ void ThreadSafeCallback::callbackFunc(Napi::Env env,
59
60
  }
60
61
 
61
62
  if (env && callback)
63
+ {
62
64
  callback.Call(context->Value(), args);
65
+ cleanup();
66
+ }
63
67
  }
@@ -11,6 +11,7 @@ class ThreadSafeCallback
11
11
  public:
12
12
  using arg_vector_t = std::vector<napi_value>;
13
13
  using arg_func_t = std::function<void(napi_env, arg_vector_t &)>;
14
+ using cleanup_func_t = std::function<void()>;
14
15
 
15
16
  ThreadSafeCallback(Napi::Function callback);
16
17
  ~ThreadSafeCallback();
@@ -21,7 +22,7 @@ public:
21
22
  ThreadSafeCallback &operator=(const ThreadSafeCallback &) = delete;
22
23
  ThreadSafeCallback &operator=(ThreadSafeCallback &&) = delete;
23
24
 
24
- void call(arg_func_t argFunc);
25
+ void call(arg_func_t argFunc, cleanup_func_t cleanupFunc = []() {});
25
26
 
26
27
  class CancelException : public std::exception
27
28
  {
@@ -32,6 +33,7 @@ private:
32
33
  struct CallbackData
33
34
  {
34
35
  arg_func_t argFunc;
36
+ cleanup_func_t cleanupFunc;
35
37
  };
36
38
 
37
39
  static void callbackFunc(Napi::Env env,
@@ -13,6 +13,14 @@ void WebSocketWrapper::CloseAll()
13
13
  inst->doClose();
14
14
  }
15
15
 
16
+ void WebSocketWrapper::CleanupAll()
17
+ {
18
+ PLOG_DEBUG << "CleanupAll() called";
19
+ auto copy(instances);
20
+ for (auto inst : copy)
21
+ inst->doCleanup();
22
+ }
23
+
16
24
  Napi::Object WebSocketWrapper::Init(Napi::Env env, Napi::Object exports)
17
25
  {
18
26
  Napi::HandleScope scope(env);
@@ -23,6 +31,7 @@ Napi::Object WebSocketWrapper::Init(Napi::Env env, Napi::Object exports)
23
31
  {
24
32
  InstanceMethod("open", &WebSocketWrapper::open),
25
33
  InstanceMethod("close", &WebSocketWrapper::close),
34
+ InstanceMethod("forceClose", &WebSocketWrapper::forceClose),
26
35
  InstanceMethod("sendMessage", &WebSocketWrapper::sendMessage),
27
36
  InstanceMethod("sendMessageBinary", &WebSocketWrapper::sendMessageBinary),
28
37
  InstanceMethod("isOpen", &WebSocketWrapper::isOpen),
@@ -34,6 +43,8 @@ Napi::Object WebSocketWrapper::Init(Napi::Env env, Napi::Object exports)
34
43
  InstanceMethod("onError", &WebSocketWrapper::onError),
35
44
  InstanceMethod("onBufferedAmountLow", &WebSocketWrapper::onBufferedAmountLow),
36
45
  InstanceMethod("onMessage", &WebSocketWrapper::onMessage),
46
+ InstanceMethod("remoteAddress", &WebSocketWrapper::remoteAddress),
47
+ InstanceMethod("path", &WebSocketWrapper::path),
37
48
  });
38
49
 
39
50
  constructor = Napi::Persistent(func);
@@ -249,17 +260,45 @@ void WebSocketWrapper::doClose()
249
260
  }
250
261
  catch (std::exception &ex)
251
262
  {
252
- std::cerr << std::string("libWebSocket error while closing WebSocket: ") + ex.what() << std::endl;
263
+ std::cerr << std::string("libdatachannel error while closing WebSocket: ") + ex.what() << std::endl;
253
264
  return;
254
265
  }
255
266
  }
256
267
 
257
268
  mOnOpenCallback.reset();
258
- mOnClosedCallback.reset();
259
269
  mOnErrorCallback.reset();
260
270
  mOnBufferedAmountLowCallback.reset();
261
271
  mOnMessageCallback.reset();
272
+ }
262
273
 
274
+ void WebSocketWrapper::doForceClose()
275
+ {
276
+ PLOG_DEBUG << "doForceClose() called";
277
+ if (mWebSocketPtr)
278
+ {
279
+ PLOG_DEBUG << "Force closing...";
280
+ try
281
+ {
282
+ mWebSocketPtr->forceClose();
283
+ mWebSocketPtr.reset();
284
+ }
285
+ catch (std::exception &ex)
286
+ {
287
+ std::cerr << std::string("libdatachannel error while force closing WebSocket: ") + ex.what() << std::endl;
288
+ return;
289
+ }
290
+ }
291
+
292
+ mOnOpenCallback.reset();
293
+ mOnErrorCallback.reset();
294
+ mOnBufferedAmountLowCallback.reset();
295
+ mOnMessageCallback.reset();
296
+ }
297
+
298
+ void WebSocketWrapper::doCleanup()
299
+ {
300
+ PLOG_DEBUG << "doCleanup() called";
301
+ mOnClosedCallback.reset();
263
302
  instances.erase(this);
264
303
  }
265
304
 
@@ -285,7 +324,7 @@ void WebSocketWrapper::open(const Napi::CallbackInfo &info)
285
324
  }
286
325
  catch (std::exception &ex)
287
326
  {
288
- Napi::Error::New(env, std::string("libWebSocket error while opening WebSocket: ") + ex.what()).ThrowAsJavaScriptException();
327
+ Napi::Error::New(env, std::string("libdatachannel error while opening WebSocket: ") + ex.what()).ThrowAsJavaScriptException();
289
328
  return;
290
329
  }
291
330
  }
@@ -296,6 +335,12 @@ void WebSocketWrapper::close(const Napi::CallbackInfo &info)
296
335
  doClose();
297
336
  }
298
337
 
338
+ void WebSocketWrapper::forceClose(const Napi::CallbackInfo &info)
339
+ {
340
+ PLOG_DEBUG << "forceClose() called";
341
+ doForceClose();
342
+ }
343
+
299
344
  Napi::Value WebSocketWrapper::sendMessage(const Napi::CallbackInfo &info)
300
345
  {
301
346
  PLOG_DEBUG << "sendMessage() called";
@@ -321,7 +366,7 @@ Napi::Value WebSocketWrapper::sendMessage(const Napi::CallbackInfo &info)
321
366
  }
322
367
  catch (std::exception &ex)
323
368
  {
324
- Napi::Error::New(env, std::string("libWebSocket error while sending data channel message: ") + ex.what()).ThrowAsJavaScriptException();
369
+ Napi::Error::New(env, std::string("libdatachannel error while sending data channel message: ") + ex.what()).ThrowAsJavaScriptException();
325
370
  return Napi::Boolean::New(info.Env(), false);
326
371
  }
327
372
  }
@@ -351,7 +396,7 @@ Napi::Value WebSocketWrapper::sendMessageBinary(const Napi::CallbackInfo &info)
351
396
  }
352
397
  catch (std::exception &ex)
353
398
  {
354
- Napi::Error::New(env, std::string("libWebSocket error while sending data channel message: ") + ex.what()).ThrowAsJavaScriptException();
399
+ Napi::Error::New(env, std::string("libdatachannel error while sending data channel message: ") + ex.what()).ThrowAsJavaScriptException();
355
400
  return Napi::Boolean::New(info.Env(), false);
356
401
  }
357
402
  }
@@ -372,7 +417,7 @@ Napi::Value WebSocketWrapper::isOpen(const Napi::CallbackInfo &info)
372
417
  }
373
418
  catch (std::exception &ex)
374
419
  {
375
- Napi::Error::New(env, std::string("libWebSocket error: ") + ex.what()).ThrowAsJavaScriptException();
420
+ Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
376
421
  return Napi::Boolean::New(info.Env(), false);
377
422
  }
378
423
  }
@@ -393,7 +438,7 @@ Napi::Value WebSocketWrapper::bufferedAmount(const Napi::CallbackInfo &info)
393
438
  }
394
439
  catch (std::exception &ex)
395
440
  {
396
- Napi::Error::New(env, std::string("libWebSocket error: ") + ex.what()).ThrowAsJavaScriptException();
441
+ Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
397
442
  return Napi::Number::New(info.Env(), 0);
398
443
  }
399
444
  }
@@ -414,11 +459,69 @@ Napi::Value WebSocketWrapper::maxMessageSize(const Napi::CallbackInfo &info)
414
459
  }
415
460
  catch (std::exception &ex)
416
461
  {
417
- Napi::Error::New(env, std::string("libWebSocket error: ") + ex.what()).ThrowAsJavaScriptException();
462
+ Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
418
463
  return Napi::Number::New(info.Env(), 0);
419
464
  }
420
465
  }
421
466
 
467
+ Napi::Value WebSocketWrapper::remoteAddress(const Napi::CallbackInfo &info)
468
+ {
469
+ PLOG_DEBUG << "remoteAddress() called";
470
+ Napi::Env env = info.Env();
471
+
472
+ if (!mWebSocketPtr)
473
+ {
474
+ return env.Undefined();
475
+ }
476
+
477
+ try
478
+ {
479
+ auto address = mWebSocketPtr->remoteAddress();
480
+ if (address.has_value())
481
+ {
482
+ return Napi::String::New(info.Env(), address.value());
483
+ }
484
+ else
485
+ {
486
+ return env.Undefined();
487
+ }
488
+ }
489
+ catch (std::exception &ex)
490
+ {
491
+ Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
492
+ return env.Undefined();
493
+ }
494
+ }
495
+
496
+ Napi::Value WebSocketWrapper::path(const Napi::CallbackInfo &info)
497
+ {
498
+ PLOG_DEBUG << "path() called";
499
+ Napi::Env env = info.Env();
500
+
501
+ if (!mWebSocketPtr)
502
+ {
503
+ return env.Undefined();
504
+ }
505
+
506
+ try
507
+ {
508
+ auto path = mWebSocketPtr->path();
509
+ if (path.has_value())
510
+ {
511
+ return Napi::String::New(info.Env(), path.value());
512
+ }
513
+ else
514
+ {
515
+ return env.Undefined();
516
+ }
517
+ }
518
+ catch (std::exception &ex)
519
+ {
520
+ Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
521
+ return env.Undefined();
522
+ }
523
+ }
524
+
422
525
  void WebSocketWrapper::setBufferedAmountLowThreshold(const Napi::CallbackInfo &info)
423
526
  {
424
527
  PLOG_DEBUG << "setBufferedAmountLowThreshold() called";
@@ -443,7 +546,7 @@ void WebSocketWrapper::setBufferedAmountLowThreshold(const Napi::CallbackInfo &i
443
546
  }
444
547
  catch (std::exception &ex)
445
548
  {
446
- Napi::Error::New(env, std::string("libWebSocket error: ") + ex.what()).ThrowAsJavaScriptException();
549
+ Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
447
550
  return;
448
551
  }
449
552
  }
@@ -488,8 +591,7 @@ void WebSocketWrapper::onOpen(const Napi::CallbackInfo &info)
488
591
  // This will run in main thread and needs to construct the
489
592
  // arguments for the call
490
593
  args = {};
491
- PLOG_DEBUG << "mOnOpenCallback call(2)"; });
492
- });
594
+ PLOG_DEBUG << "mOnOpenCallback call(2)"; }); });
493
595
  }
494
596
 
495
597
  void WebSocketWrapper::onClosed(const Napi::CallbackInfo &info)
@@ -524,6 +626,8 @@ void WebSocketWrapper::onClosed(const Napi::CallbackInfo &info)
524
626
  // This will run in main thread and needs to construct the
525
627
  // arguments for the call
526
628
  args = {};
629
+ },[this]{
630
+ doCleanup();
527
631
  }); });
528
632
  }
529
633
 
@@ -22,13 +22,16 @@ public:
22
22
 
23
23
  // Functions
24
24
  void open(const Napi::CallbackInfo &info);
25
- void close(const Napi::CallbackInfo &info);
25
+ void close(const Napi::CallbackInfo &info);
26
+ void forceClose(const Napi::CallbackInfo &info);
26
27
  Napi::Value sendMessage(const Napi::CallbackInfo &info);
27
28
  Napi::Value sendMessageBinary(const Napi::CallbackInfo &info);
28
29
  Napi::Value isOpen(const Napi::CallbackInfo &info);
29
30
  Napi::Value bufferedAmount(const Napi::CallbackInfo &info);
30
31
  Napi::Value maxMessageSize(const Napi::CallbackInfo &info);
31
32
  void setBufferedAmountLowThreshold(const Napi::CallbackInfo &info);
33
+ Napi::Value remoteAddress(const Napi::CallbackInfo &info);
34
+ Napi::Value path(const Napi::CallbackInfo &info);
32
35
 
33
36
  // Callbacks
34
37
  void onOpen(const Napi::CallbackInfo &info);
@@ -40,10 +43,15 @@ public:
40
43
  // Close all existing WebSockets
41
44
  static void CloseAll();
42
45
 
46
+ // Reset all Callbacks for existing WebSockets
47
+ static void CleanupAll();
48
+
43
49
  private:
44
- static std::unordered_set<WebSocketWrapper*> instances;
50
+ static std::unordered_set<WebSocketWrapper *> instances;
45
51
 
46
52
  void doClose();
53
+ void doForceClose();
54
+ void doCleanup();
47
55
 
48
56
  std::shared_ptr<rtc::WebSocket> mWebSocketPtr = nullptr;
49
57