node-datachannel 0.29.0 → 0.31.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/.clang-format +17 -0
- package/CMakeLists.txt +16 -2
- package/dist/cjs/lib/index.cjs +21 -0
- package/dist/cjs/lib/index.cjs.map +1 -1
- package/dist/cjs/polyfill/RTCPeerConnection.cjs +6 -1
- package/dist/cjs/polyfill/RTCPeerConnection.cjs.map +1 -1
- package/dist/esm/lib/index.mjs +15 -1
- package/dist/esm/lib/index.mjs.map +1 -1
- package/dist/esm/polyfill/RTCPeerConnection.mjs +6 -1
- package/dist/esm/polyfill/RTCPeerConnection.mjs.map +1 -1
- package/dist/types/lib/index.d.ts +58 -4
- package/dist/types/lib/types.d.ts +3 -1
- package/package.json +3 -2
- package/rollup.config.mjs +1 -1
- package/src/cpp/data-channel-wrapper.cpp +432 -411
- package/src/cpp/data-channel-wrapper.h +0 -2
- package/src/cpp/ice-udp-mux-listener-wrapper.cpp +104 -97
- package/src/cpp/main.cpp +25 -11
- package/src/cpp/media-audio-wrapper.cpp +291 -294
- package/src/cpp/media-audio-wrapper.h +1 -3
- package/src/cpp/media-av1packetization.cpp +24 -0
- package/src/cpp/media-av1packetization.h +11 -0
- package/src/cpp/media-av1rtppacketizer-wrapper.cpp +126 -0
- package/src/cpp/media-av1rtppacketizer-wrapper.h +29 -0
- package/src/cpp/media-direction.cpp +32 -32
- package/src/cpp/media-direction.h +1 -1
- package/src/cpp/media-h264rtppacketizer-wrapper.cpp +126 -0
- package/src/cpp/media-h264rtppacketizer-wrapper.h +30 -0
- package/src/cpp/media-h265rtppacketizer-wrapper.cpp +126 -0
- package/src/cpp/media-h265rtppacketizer-wrapper.h +30 -0
- package/src/cpp/media-h26xseparator.cpp +32 -0
- package/src/cpp/media-h26xseparator.h +11 -0
- package/src/cpp/media-mediahandler-helper.cpp +28 -0
- package/src/cpp/media-mediahandler-helper.h +11 -0
- package/src/cpp/media-rtcpnackresponder-wrapper.cpp +68 -0
- package/src/cpp/media-rtcpnackresponder-wrapper.h +28 -0
- package/src/cpp/media-rtcpreceivingsession-wrapper.cpp +38 -25
- package/src/cpp/media-rtcpreceivingsession-wrapper.h +1 -6
- package/src/cpp/media-rtcpsrreporter-wrapper.cpp +93 -0
- package/src/cpp/media-rtcpsrreporter-wrapper.h +30 -0
- package/src/cpp/media-rtppacketizationconfig-wrapper.cpp +167 -0
- package/src/cpp/media-rtppacketizationconfig-wrapper.h +35 -0
- package/src/cpp/media-rtppacketizer-wrapper.cpp +95 -0
- package/src/cpp/media-rtppacketizer-wrapper.h +30 -0
- package/src/cpp/media-track-wrapper.cpp +356 -340
- package/src/cpp/media-track-wrapper.h +0 -3
- package/src/cpp/media-video-wrapper.cpp +347 -313
- package/src/cpp/media-video-wrapper.h +3 -3
- package/src/cpp/peer-connection-wrapper.cpp +1094 -1047
- package/src/cpp/peer-connection-wrapper.h +0 -2
- package/src/cpp/rtc-wrapper.cpp +142 -138
- package/src/cpp/rtc-wrapper.h +8 -10
- package/src/cpp/thread-safe-callback.cpp +39 -50
- package/src/cpp/thread-safe-callback.h +26 -28
- package/src/cpp/web-socket-server-wrapper.cpp +205 -199
- package/src/cpp/web-socket-server-wrapper.h +0 -4
- package/src/cpp/web-socket-wrapper.cpp +625 -598
- package/src/cpp/web-socket-wrapper.h +0 -3
- package/src/lib/index.ts +69 -2
- package/src/lib/types.ts +6 -0
- package/src/polyfill/RTCPeerConnection.ts +8 -2
package/src/cpp/rtc-wrapper.cpp
CHANGED
|
@@ -18,184 +18,188 @@
|
|
|
18
18
|
|
|
19
19
|
Napi::Object RtcWrapper::Init(Napi::Env env, Napi::Object exports)
|
|
20
20
|
{
|
|
21
|
-
|
|
21
|
+
Napi::HandleScope scope(env);
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
exports.Set("initLogger", Napi::Function::New(env, &RtcWrapper::initLogger));
|
|
24
|
+
exports.Set("cleanup", Napi::Function::New(env, &RtcWrapper::cleanup));
|
|
25
|
+
exports.Set("preload", Napi::Function::New(env, &RtcWrapper::preload));
|
|
26
|
+
exports.Set("setSctpSettings", Napi::Function::New(env, &RtcWrapper::setSctpSettings));
|
|
27
|
+
exports.Set("getLibraryVersion", Napi::Function::New(env, &RtcWrapper::getLibraryVersion));
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
return exports;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
void RtcWrapper::preload(const Napi::CallbackInfo &info)
|
|
33
33
|
{
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
34
|
+
PLOG_DEBUG << "preload() called";
|
|
35
|
+
Napi::Env env = info.Env();
|
|
36
|
+
try
|
|
37
|
+
{
|
|
38
|
+
rtc::Preload();
|
|
39
|
+
}
|
|
40
|
+
catch (std::exception &ex)
|
|
41
|
+
{
|
|
42
|
+
Napi::Error::New(env, std::string("libdatachannel error# ") + ex.what()).ThrowAsJavaScriptException();
|
|
43
|
+
}
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
void RtcWrapper::initLogger(const Napi::CallbackInfo &info)
|
|
47
47
|
{
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
48
|
+
Napi::Env env = info.Env();
|
|
49
|
+
int length = info.Length();
|
|
50
|
+
|
|
51
|
+
// We expect (String, Object, Function) as param
|
|
52
|
+
if (length < 1 || !info[0].IsString())
|
|
53
|
+
{
|
|
54
|
+
Napi::TypeError::New(env, "LogLevel(String) expected").ThrowAsJavaScriptException();
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
std::string logLevelStr = info[0].As<Napi::String>().ToString();
|
|
59
|
+
rtc::LogLevel logLevel = rtc::LogLevel::None;
|
|
60
|
+
|
|
61
|
+
if (logLevelStr == "Verbose")
|
|
62
|
+
logLevel = rtc::LogLevel::Verbose;
|
|
63
|
+
if (logLevelStr == "Debug")
|
|
64
|
+
logLevel = rtc::LogLevel::Debug;
|
|
65
|
+
if (logLevelStr == "Info")
|
|
66
|
+
logLevel = rtc::LogLevel::Info;
|
|
67
|
+
if (logLevelStr == "Warning")
|
|
68
|
+
logLevel = rtc::LogLevel::Warning;
|
|
69
|
+
if (logLevelStr == "Error")
|
|
70
|
+
logLevel = rtc::LogLevel::Error;
|
|
71
|
+
if (logLevelStr == "Fatal")
|
|
72
|
+
logLevel = rtc::LogLevel::Fatal;
|
|
73
|
+
|
|
74
|
+
try
|
|
75
|
+
{
|
|
76
|
+
if (length < 2)
|
|
53
77
|
{
|
|
54
|
-
|
|
55
|
-
return;
|
|
78
|
+
rtc::InitLogger(logLevel);
|
|
56
79
|
}
|
|
57
|
-
|
|
58
|
-
std::string logLevelStr = info[0].As<Napi::String>().ToString();
|
|
59
|
-
rtc::LogLevel logLevel = rtc::LogLevel::None;
|
|
60
|
-
|
|
61
|
-
if (logLevelStr == "Verbose")
|
|
62
|
-
logLevel = rtc::LogLevel::Verbose;
|
|
63
|
-
if (logLevelStr == "Debug")
|
|
64
|
-
logLevel = rtc::LogLevel::Debug;
|
|
65
|
-
if (logLevelStr == "Info")
|
|
66
|
-
logLevel = rtc::LogLevel::Info;
|
|
67
|
-
if (logLevelStr == "Warning")
|
|
68
|
-
logLevel = rtc::LogLevel::Warning;
|
|
69
|
-
if (logLevelStr == "Error")
|
|
70
|
-
logLevel = rtc::LogLevel::Error;
|
|
71
|
-
if (logLevelStr == "Fatal")
|
|
72
|
-
logLevel = rtc::LogLevel::Fatal;
|
|
73
|
-
|
|
74
|
-
try
|
|
75
|
-
{
|
|
76
|
-
if (length < 2)
|
|
77
|
-
{
|
|
78
|
-
rtc::InitLogger(logLevel);
|
|
79
|
-
}
|
|
80
|
-
else
|
|
81
|
-
{
|
|
82
|
-
if (!info[1].IsFunction())
|
|
83
|
-
{
|
|
84
|
-
Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
logCallback = std::make_unique<ThreadSafeCallback>(info[1].As<Napi::Function>());
|
|
88
|
-
rtc::InitLogger(logLevel, [&](rtc::LogLevel level, std::string message)
|
|
89
|
-
{
|
|
90
|
-
if (logCallback)
|
|
91
|
-
logCallback->call([level, message = std::move(message)](Napi::Env env, std::vector<napi_value> &args) {
|
|
92
|
-
// This will run in main thread and needs to construct the
|
|
93
|
-
// arguments for the call
|
|
94
|
-
|
|
95
|
-
std::string logLevel;
|
|
96
|
-
if (level == rtc::LogLevel::Verbose)
|
|
97
|
-
logLevel = "Verbose";
|
|
98
|
-
if (level == rtc::LogLevel::Debug)
|
|
99
|
-
logLevel = "Debug";
|
|
100
|
-
if (level == rtc::LogLevel::Info)
|
|
101
|
-
logLevel = "Info";
|
|
102
|
-
if (level == rtc::LogLevel::Warning)
|
|
103
|
-
logLevel = "Warning";
|
|
104
|
-
if (level == rtc::LogLevel::Error)
|
|
105
|
-
logLevel = "Error";
|
|
106
|
-
if (level == rtc::LogLevel::Fatal)
|
|
107
|
-
logLevel = "Fatal";
|
|
108
|
-
args = {Napi::String::New(env, logLevel), Napi::String::New(env, message)};
|
|
109
|
-
}); });
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
catch (std::exception &ex)
|
|
80
|
+
else
|
|
113
81
|
{
|
|
114
|
-
|
|
82
|
+
if (!info[1].IsFunction())
|
|
83
|
+
{
|
|
84
|
+
Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
|
|
115
85
|
return;
|
|
86
|
+
}
|
|
87
|
+
logCallback = std::make_unique<ThreadSafeCallback>(info[1].As<Napi::Function>());
|
|
88
|
+
rtc::InitLogger(logLevel,
|
|
89
|
+
[&](rtc::LogLevel level, std::string message)
|
|
90
|
+
{
|
|
91
|
+
if (logCallback)
|
|
92
|
+
logCallback->call(
|
|
93
|
+
[level, message = std::move(message)](Napi::Env env, std::vector<napi_value> &args)
|
|
94
|
+
{
|
|
95
|
+
// This will run in main thread and needs to construct the
|
|
96
|
+
// arguments for the call
|
|
97
|
+
|
|
98
|
+
std::string logLevel;
|
|
99
|
+
if (level == rtc::LogLevel::Verbose)
|
|
100
|
+
logLevel = "Verbose";
|
|
101
|
+
if (level == rtc::LogLevel::Debug)
|
|
102
|
+
logLevel = "Debug";
|
|
103
|
+
if (level == rtc::LogLevel::Info)
|
|
104
|
+
logLevel = "Info";
|
|
105
|
+
if (level == rtc::LogLevel::Warning)
|
|
106
|
+
logLevel = "Warning";
|
|
107
|
+
if (level == rtc::LogLevel::Error)
|
|
108
|
+
logLevel = "Error";
|
|
109
|
+
if (level == rtc::LogLevel::Fatal)
|
|
110
|
+
logLevel = "Fatal";
|
|
111
|
+
args = {Napi::String::New(env, logLevel), Napi::String::New(env, message)};
|
|
112
|
+
});
|
|
113
|
+
});
|
|
116
114
|
}
|
|
115
|
+
}
|
|
116
|
+
catch (std::exception &ex)
|
|
117
|
+
{
|
|
118
|
+
Napi::Error::New(env, std::string("libdatachannel error# ") + ex.what()).ThrowAsJavaScriptException();
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
117
121
|
}
|
|
118
122
|
|
|
119
123
|
void RtcWrapper::cleanup(const Napi::CallbackInfo &info)
|
|
120
124
|
{
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
125
|
+
PLOG_DEBUG << "cleanup() called";
|
|
126
|
+
Napi::Env env = info.Env();
|
|
127
|
+
try
|
|
128
|
+
{
|
|
129
|
+
PeerConnectionWrapper::CloseAll();
|
|
130
|
+
DataChannelWrapper::CloseAll();
|
|
127
131
|
|
|
128
132
|
#if RTC_ENABLE_MEDIA == 1
|
|
129
|
-
|
|
133
|
+
TrackWrapper::CloseAll();
|
|
130
134
|
#endif
|
|
131
135
|
|
|
132
136
|
#if RTC_ENABLE_WEBSOCKET == 1
|
|
133
|
-
|
|
134
|
-
|
|
137
|
+
WebSocketWrapper::CloseAll();
|
|
138
|
+
WebSocketServerWrapper::StopAll();
|
|
135
139
|
#endif
|
|
136
140
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
141
|
+
const auto timeout = std::chrono::seconds(10);
|
|
142
|
+
if (rtc::Cleanup().wait_for(std::chrono::seconds(timeout)) == std::future_status::timeout)
|
|
143
|
+
throw std::runtime_error("cleanup timeout (possible deadlock)");
|
|
140
144
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
145
|
+
// Cleanup the instances
|
|
146
|
+
PeerConnectionWrapper::CleanupAll();
|
|
147
|
+
DataChannelWrapper::CleanupAll();
|
|
144
148
|
|
|
145
149
|
#if RTC_ENABLE_MEDIA == 1
|
|
146
|
-
|
|
150
|
+
TrackWrapper::CleanupAll();
|
|
147
151
|
#endif
|
|
148
152
|
|
|
149
153
|
#if RTC_ENABLE_WEBSOCKET == 1
|
|
150
|
-
|
|
154
|
+
WebSocketWrapper::CleanupAll();
|
|
151
155
|
#endif
|
|
152
156
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
157
|
+
if (logCallback)
|
|
158
|
+
logCallback.reset();
|
|
159
|
+
}
|
|
160
|
+
catch (std::exception &ex)
|
|
161
|
+
{
|
|
162
|
+
Napi::Error::New(env, std::string("libdatachannel error# ") + ex.what()).ThrowAsJavaScriptException();
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
161
165
|
}
|
|
162
166
|
|
|
163
167
|
void RtcWrapper::setSctpSettings(const Napi::CallbackInfo &info)
|
|
164
168
|
{
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
169
|
+
PLOG_DEBUG << "setSctpSettings() called";
|
|
170
|
+
Napi::Env env = info.Env();
|
|
171
|
+
int length = info.Length();
|
|
172
|
+
|
|
173
|
+
// We expect (Object) as param
|
|
174
|
+
if (length < 1 || !info[0].IsObject())
|
|
175
|
+
{
|
|
176
|
+
Napi::TypeError::New(env, "Configuration (Object) expected").ThrowAsJavaScriptException();
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
rtc::SctpSettings settings;
|
|
181
|
+
Napi::Object config = info[0].As<Napi::Object>();
|
|
182
|
+
|
|
183
|
+
if (config.Get("recvBufferSize").IsNumber())
|
|
184
|
+
settings.recvBufferSize = config.Get("recvBufferSize").As<Napi::Number>().Uint32Value();
|
|
185
|
+
if (config.Get("sendBufferSize").IsNumber())
|
|
186
|
+
settings.sendBufferSize = config.Get("sendBufferSize").As<Napi::Number>().Uint32Value();
|
|
187
|
+
if (config.Get("maxChunksOnQueue").IsNumber())
|
|
188
|
+
settings.maxChunksOnQueue = config.Get("maxChunksOnQueue").As<Napi::Number>().Uint32Value();
|
|
189
|
+
if (config.Get("initialCongestionWindow").IsNumber())
|
|
190
|
+
settings.initialCongestionWindow = config.Get("initialCongestionWindow").As<Napi::Number>().Uint32Value();
|
|
191
|
+
if (config.Get("congestionControlModule").IsNumber())
|
|
192
|
+
settings.congestionControlModule = config.Get("congestionControlModule").As<Napi::Number>().Uint32Value();
|
|
193
|
+
if (config.Get("delayedSackTime").IsNumber())
|
|
194
|
+
settings.delayedSackTime =
|
|
195
|
+
std::chrono::milliseconds(config.Get("delayedSackTime").As<Napi::Number>().Uint32Value());
|
|
196
|
+
|
|
197
|
+
rtc::SetSctpSettings(settings);
|
|
193
198
|
}
|
|
194
199
|
|
|
195
|
-
|
|
196
200
|
Napi::Value RtcWrapper::getLibraryVersion(const Napi::CallbackInfo &info)
|
|
197
201
|
{
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
202
|
+
PLOG_DEBUG << "getLibraryVersion() called";
|
|
203
|
+
Napi::Env env = info.Env();
|
|
204
|
+
return Napi::String::New(info.Env(), RTC_VERSION);
|
|
201
205
|
}
|
package/src/cpp/rtc-wrapper.h
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
#ifndef RTC_WRAPPER_H
|
|
2
2
|
#define RTC_WRAPPER_H
|
|
3
3
|
|
|
4
|
-
#include <iostream>
|
|
5
|
-
#include <string>
|
|
6
|
-
|
|
7
4
|
#include <napi.h>
|
|
8
5
|
|
|
9
6
|
#include "rtc/rtc.hpp"
|
|
@@ -13,14 +10,15 @@
|
|
|
13
10
|
class RtcWrapper
|
|
14
11
|
{
|
|
15
12
|
public:
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
13
|
+
static Napi::Object Init(Napi::Env env, Napi::Object exports);
|
|
14
|
+
static void preload(const Napi::CallbackInfo &info);
|
|
15
|
+
static void initLogger(const Napi::CallbackInfo &info);
|
|
16
|
+
static void cleanup(const Napi::CallbackInfo &info);
|
|
17
|
+
static void setSctpSettings(const Napi::CallbackInfo &info);
|
|
18
|
+
static Napi::Value getLibraryVersion(const Napi::CallbackInfo &info);
|
|
19
|
+
|
|
22
20
|
private:
|
|
23
|
-
|
|
21
|
+
static inline std::unique_ptr<ThreadSafeCallback> logCallback = nullptr;
|
|
24
22
|
};
|
|
25
23
|
|
|
26
24
|
#endif // RTC_WRAPPER_H
|
|
@@ -2,67 +2,56 @@
|
|
|
2
2
|
|
|
3
3
|
#include <stdexcept>
|
|
4
4
|
|
|
5
|
-
const char *ThreadSafeCallback::CancelException::what() const throw()
|
|
6
|
-
{
|
|
7
|
-
return "ThreadSafeCallback cancelled";
|
|
8
|
-
}
|
|
5
|
+
const char *ThreadSafeCallback::CancelException::what() const throw() { return "ThreadSafeCallback cancelled"; }
|
|
9
6
|
|
|
10
7
|
ThreadSafeCallback::ThreadSafeCallback(Napi::Function callback)
|
|
11
8
|
{
|
|
12
|
-
|
|
9
|
+
Napi::Env env = callback.Env();
|
|
13
10
|
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
if (!callback.IsFunction())
|
|
12
|
+
throw Napi::Error::New(env, "Callback must be a function");
|
|
16
13
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
0, // unlimited queue
|
|
21
|
-
1);
|
|
14
|
+
tsfn = tsfn_t::New(env, std::move(callback), "ThreadSafeCallback callback",
|
|
15
|
+
0, // unlimited queue
|
|
16
|
+
1);
|
|
22
17
|
}
|
|
23
18
|
|
|
24
|
-
ThreadSafeCallback::~ThreadSafeCallback()
|
|
25
|
-
{
|
|
26
|
-
tsfn.Abort();
|
|
27
|
-
}
|
|
19
|
+
ThreadSafeCallback::~ThreadSafeCallback() { tsfn.Abort(); }
|
|
28
20
|
|
|
29
21
|
void ThreadSafeCallback::call(arg_func_t argFunc, cleanup_func_t cleanupFunc)
|
|
30
22
|
{
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
23
|
+
CallbackData *data = new CallbackData{std::move(argFunc), std::move(cleanupFunc)};
|
|
24
|
+
if (tsfn.BlockingCall(data) != napi_ok)
|
|
25
|
+
{
|
|
26
|
+
delete data;
|
|
27
|
+
throw std::runtime_error("Failed to call JavaScript callback");
|
|
28
|
+
}
|
|
37
29
|
}
|
|
38
30
|
|
|
39
|
-
void ThreadSafeCallback::callbackFunc(Napi::Env env,
|
|
40
|
-
Napi::Function callback,
|
|
41
|
-
ContextType *context,
|
|
42
|
-
CallbackData *data)
|
|
31
|
+
void ThreadSafeCallback::callbackFunc(Napi::Env env, Napi::Function callback, ContextType *context, CallbackData *data)
|
|
43
32
|
{
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
33
|
+
// if env is gone, it could mean this cb was destroyed. See issue#176
|
|
34
|
+
if (!data || !env)
|
|
35
|
+
return;
|
|
36
|
+
|
|
37
|
+
arg_vector_t args;
|
|
38
|
+
arg_func_t argFunc(std::move(data->argFunc));
|
|
39
|
+
cleanup_func_t cleanup(std::move(data->cleanupFunc));
|
|
40
|
+
delete data;
|
|
41
|
+
|
|
42
|
+
try
|
|
43
|
+
{
|
|
44
|
+
argFunc(env, args);
|
|
45
|
+
}
|
|
46
|
+
catch (CancelException &)
|
|
47
|
+
{
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (callback)
|
|
52
|
+
{
|
|
53
|
+
callback.Call(args);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
cleanup();
|
|
68
57
|
}
|
|
@@ -9,41 +9,39 @@
|
|
|
9
9
|
class ThreadSafeCallback
|
|
10
10
|
{
|
|
11
11
|
public:
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
using arg_vector_t = std::vector<napi_value>;
|
|
13
|
+
using arg_func_t = std::function<void(napi_env, arg_vector_t &)>;
|
|
14
|
+
using cleanup_func_t = std::function<void()>;
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
ThreadSafeCallback(Napi::Function callback);
|
|
17
|
+
~ThreadSafeCallback();
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
ThreadSafeCallback(const ThreadSafeCallback &) = delete;
|
|
20
|
+
ThreadSafeCallback(ThreadSafeCallback &&) = delete;
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
ThreadSafeCallback &operator=(const ThreadSafeCallback &) = delete;
|
|
23
|
+
ThreadSafeCallback &operator=(ThreadSafeCallback &&) = delete;
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
void call(
|
|
26
|
+
arg_func_t argFunc, cleanup_func_t cleanupFunc = []() {});
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
class CancelException : public std::exception
|
|
29
|
+
{
|
|
30
|
+
const char *what() const throw();
|
|
31
|
+
};
|
|
31
32
|
|
|
32
33
|
private:
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
using tsfn_t = Napi::TypedThreadSafeFunction<ContextType, CallbackData, callbackFunc>;
|
|
46
|
-
tsfn_t tsfn;
|
|
34
|
+
using ContextType = std::nullptr_t;
|
|
35
|
+
struct CallbackData
|
|
36
|
+
{
|
|
37
|
+
arg_func_t argFunc;
|
|
38
|
+
cleanup_func_t cleanupFunc;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
static void callbackFunc(Napi::Env env, Napi::Function callback, ContextType *context, CallbackData *data);
|
|
42
|
+
|
|
43
|
+
using tsfn_t = Napi::TypedThreadSafeFunction<ContextType, CallbackData, callbackFunc>;
|
|
44
|
+
tsfn_t tsfn;
|
|
47
45
|
};
|
|
48
46
|
|
|
49
47
|
#endif // THREAD_SAFE_CALLBACK_H
|