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.
- package/CMakeLists.txt +2 -2
- package/examples/electron-demo/package.json +1 -1
- package/jest.config.cjs +7 -0
- package/lib/index.cjs +142 -0
- package/lib/index.d.cts +313 -0
- package/lib/index.d.ts +4 -1
- package/package.json +25 -6
- package/polyfill/RTCPeerConnection.js +0 -1
- package/polyfill/index.cjs +1069 -0
- package/polyfill/index.d.cts +37 -0
- package/src/data-channel-wrapper.cpp +15 -1
- package/src/data-channel-wrapper.h +5 -1
- package/src/media-track-wrapper.cpp +25 -5
- package/src/media-track-wrapper.h +7 -3
- package/src/peer-connection-wrapper.cpp +21 -27
- package/src/peer-connection-wrapper.h +2 -5
- package/src/rtc-wrapper.cpp +5 -2
- package/src/thread-safe-callback.cpp +6 -2
- package/src/thread-safe-callback.h +3 -1
- package/src/web-socket-wrapper.cpp +115 -11
- package/src/web-socket-wrapper.h +10 -2
- package/test/jest-tests/basic.test.js +37 -0
- package/test/jest-tests/multiple-run.test.js +73 -0
- package/test/jest-tests/p2p.test.js +99 -0
- package/test/jest-tests/streams.test.js +48 -0
- package/test/jest-tests/websocket.test.js +69 -0
- package/test/websockets.js +4 -2
- package/test/test.js +0 -252
|
@@ -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
|
|
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
|
-
|
|
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::
|
|
23
|
+
void PeerConnectionWrapper::CleanupAll()
|
|
24
24
|
{
|
|
25
|
-
PLOG_DEBUG << "
|
|
25
|
+
PLOG_DEBUG << "CleanupAll() called";
|
|
26
26
|
auto copy(instances);
|
|
27
27
|
for (auto inst : copy)
|
|
28
|
-
inst->
|
|
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
|
-
|
|
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
|
-
|
|
286
|
+
void PeerConnectionWrapper::close(const Napi::CallbackInfo &info)
|
|
287
|
+
{
|
|
288
|
+
PLOG_DEBUG << "close() called";
|
|
289
|
+
doClose();
|
|
304
290
|
}
|
|
305
291
|
|
|
306
|
-
void PeerConnectionWrapper::
|
|
292
|
+
void PeerConnectionWrapper::doCleanup()
|
|
307
293
|
{
|
|
308
|
-
PLOG_DEBUG << "
|
|
309
|
-
|
|
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
|
|
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
|
|
69
|
-
void doResetCallbacks();
|
|
66
|
+
void doCleanup();
|
|
70
67
|
|
|
71
68
|
std::string mPeerName;
|
|
72
69
|
std::unique_ptr<rtc::PeerConnection> mRtcPeerConnPtr = nullptr;
|
package/src/rtc-wrapper.cpp
CHANGED
|
@@ -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
|
-
//
|
|
129
|
-
PeerConnectionWrapper::
|
|
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("
|
|
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("
|
|
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("
|
|
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("
|
|
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("
|
|
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("
|
|
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("
|
|
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("
|
|
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
|
|
package/src/web-socket-wrapper.h
CHANGED
|
@@ -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
|
|