node-datachannel 0.29.0 → 0.30.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 +5 -1
- package/dist/cjs/polyfill/RTCPeerConnection.cjs +6 -1
- package/dist/cjs/polyfill/RTCPeerConnection.cjs.map +1 -1
- package/dist/esm/polyfill/RTCPeerConnection.mjs +6 -1
- package/dist/esm/polyfill/RTCPeerConnection.mjs.map +1 -1
- package/dist/types/polyfill/RTCPeerConnection.d.ts +1 -2
- package/package.json +3 -2
- 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 +11 -11
- package/src/cpp/media-audio-wrapper.cpp +291 -294
- package/src/cpp/media-audio-wrapper.h +1 -3
- package/src/cpp/media-direction.cpp +32 -32
- package/src/cpp/media-direction.h +1 -1
- package/src/cpp/media-rtcpreceivingsession-wrapper.cpp +24 -28
- package/src/cpp/media-rtcpreceivingsession-wrapper.h +0 -5
- package/src/cpp/media-track-wrapper.cpp +350 -339
- package/src/cpp/media-track-wrapper.h +0 -3
- package/src/cpp/media-video-wrapper.cpp +312 -313
- package/src/cpp/media-video-wrapper.h +1 -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/polyfill/RTCPeerConnection.ts +9 -3
|
@@ -7,763 +7,790 @@ std::unordered_set<WebSocketWrapper *> WebSocketWrapper::instances;
|
|
|
7
7
|
|
|
8
8
|
void WebSocketWrapper::CloseAll()
|
|
9
9
|
{
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
PLOG_DEBUG << "CloseAll() called";
|
|
11
|
+
auto copy(instances);
|
|
12
|
+
for (auto inst : copy)
|
|
13
|
+
inst->doClose();
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
void WebSocketWrapper::CleanupAll()
|
|
17
17
|
{
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
PLOG_DEBUG << "CleanupAll() called";
|
|
19
|
+
auto copy(instances);
|
|
20
|
+
for (auto inst : copy)
|
|
21
|
+
inst->doCleanup();
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
Napi::Object WebSocketWrapper::Init(Napi::Env env, Napi::Object exports)
|
|
25
25
|
{
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
return exports;
|
|
26
|
+
Napi::HandleScope scope(env);
|
|
27
|
+
|
|
28
|
+
Napi::Function func =
|
|
29
|
+
DefineClass(env, "WebSocket",
|
|
30
|
+
{
|
|
31
|
+
InstanceMethod("open", &WebSocketWrapper::open),
|
|
32
|
+
InstanceMethod("close", &WebSocketWrapper::close),
|
|
33
|
+
InstanceMethod("forceClose", &WebSocketWrapper::forceClose),
|
|
34
|
+
InstanceMethod("sendMessage", &WebSocketWrapper::sendMessage),
|
|
35
|
+
InstanceMethod("sendMessageBinary", &WebSocketWrapper::sendMessageBinary),
|
|
36
|
+
InstanceMethod("isOpen", &WebSocketWrapper::isOpen),
|
|
37
|
+
InstanceMethod("bufferedAmount", &WebSocketWrapper::bufferedAmount),
|
|
38
|
+
InstanceMethod("maxMessageSize", &WebSocketWrapper::maxMessageSize),
|
|
39
|
+
InstanceMethod("setBufferedAmountLowThreshold", &WebSocketWrapper::setBufferedAmountLowThreshold),
|
|
40
|
+
InstanceMethod("onOpen", &WebSocketWrapper::onOpen),
|
|
41
|
+
InstanceMethod("onClosed", &WebSocketWrapper::onClosed),
|
|
42
|
+
InstanceMethod("onError", &WebSocketWrapper::onError),
|
|
43
|
+
InstanceMethod("onBufferedAmountLow", &WebSocketWrapper::onBufferedAmountLow),
|
|
44
|
+
InstanceMethod("onMessage", &WebSocketWrapper::onMessage),
|
|
45
|
+
InstanceMethod("remoteAddress", &WebSocketWrapper::remoteAddress),
|
|
46
|
+
InstanceMethod("path", &WebSocketWrapper::path),
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// If this is not the first call, we don't want to reassign the constructor (hot-reload problem)
|
|
50
|
+
if (constructor.IsEmpty())
|
|
51
|
+
{
|
|
52
|
+
constructor = Napi::Persistent(func);
|
|
53
|
+
constructor.SuppressDestruct();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
exports.Set("WebSocket", func);
|
|
57
|
+
return exports;
|
|
59
58
|
}
|
|
60
59
|
|
|
61
60
|
WebSocketWrapper::WebSocketWrapper(const Napi::CallbackInfo &info) : Napi::ObjectWrap<WebSocketWrapper>(info)
|
|
62
61
|
{
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
PLOG_DEBUG << "Constructor called";
|
|
63
|
+
Napi::Env env = info.Env();
|
|
64
|
+
|
|
65
|
+
// Create WebSocket using rtc::WebSocket provided by WebSocketServer
|
|
66
|
+
if (info.Length() > 1)
|
|
67
|
+
{
|
|
68
|
+
mWebSocketPtr = *(info[1].As<Napi::External<std::shared_ptr<rtc::WebSocket>>>().Data());
|
|
69
|
+
PLOG_DEBUG << "Using WebSocket got from WebSocketServer";
|
|
70
|
+
instances.insert(this);
|
|
65
71
|
|
|
66
|
-
//
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
instances.insert(this);
|
|
72
|
+
// Closed callback must be set to trigger cleanup
|
|
73
|
+
mOnClosedCallback =
|
|
74
|
+
std::make_unique<ThreadSafeCallback>(Napi::Function::New(info.Env(), [](const Napi::CallbackInfo &) {}));
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
72
77
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
78
|
+
// Create WebSocket without config
|
|
79
|
+
if (info.Length() == 0)
|
|
80
|
+
{
|
|
81
|
+
try
|
|
82
|
+
{
|
|
83
|
+
PLOG_DEBUG << "Creating a new WebSocket without config";
|
|
84
|
+
mWebSocketPtr = std::make_unique<rtc::WebSocket>();
|
|
76
85
|
}
|
|
77
|
-
|
|
78
|
-
// Create WebSocket without config
|
|
79
|
-
if (info.Length() == 0)
|
|
86
|
+
catch (std::exception &ex)
|
|
80
87
|
{
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
mWebSocketPtr = std::make_unique<rtc::WebSocket>();
|
|
85
|
-
}
|
|
86
|
-
catch (std::exception &ex)
|
|
87
|
-
{
|
|
88
|
-
Napi::Error::New(env, std::string("libdatachannel error while creating WebSocket without config: ") + ex.what()).ThrowAsJavaScriptException();
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
instances.insert(this);
|
|
92
|
-
|
|
93
|
-
// Closed callback must be set to trigger cleanup
|
|
94
|
-
mOnClosedCallback = std::make_unique<ThreadSafeCallback>(Napi::Function::New(info.Env(), [](const Napi::CallbackInfo &) {}));
|
|
95
|
-
return;
|
|
88
|
+
Napi::Error::New(env, std::string("libdatachannel error while creating WebSocket without config: ") + ex.what())
|
|
89
|
+
.ThrowAsJavaScriptException();
|
|
90
|
+
return;
|
|
96
91
|
}
|
|
92
|
+
instances.insert(this);
|
|
97
93
|
|
|
98
|
-
//
|
|
99
|
-
|
|
94
|
+
// Closed callback must be set to trigger cleanup
|
|
95
|
+
mOnClosedCallback =
|
|
96
|
+
std::make_unique<ThreadSafeCallback>(Napi::Function::New(info.Env(), [](const Napi::CallbackInfo &) {}));
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
100
99
|
|
|
101
|
-
|
|
102
|
-
|
|
100
|
+
// Create WebSocket with config
|
|
101
|
+
PLOG_DEBUG << "Creating a new WebSocket with config";
|
|
103
102
|
|
|
104
|
-
|
|
103
|
+
Napi::Object config = info[0].As<Napi::Object>();
|
|
104
|
+
rtc::WebSocketConfiguration webSocketConfig;
|
|
105
|
+
|
|
106
|
+
if (config.Has("disableTlsVerification"))
|
|
107
|
+
{
|
|
108
|
+
if (!config.Get("disableTlsVerification").IsBoolean())
|
|
105
109
|
{
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
Napi::TypeError::New(info.Env(), "disableTlsVerification must be boolean").ThrowAsJavaScriptException();
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
webSocketConfig.disableTlsVerification = config.Get("disableTlsVerification").ToBoolean();
|
|
110
|
+
Napi::TypeError::New(info.Env(), "disableTlsVerification must be boolean").ThrowAsJavaScriptException();
|
|
111
|
+
return;
|
|
112
112
|
}
|
|
113
|
+
webSocketConfig.disableTlsVerification = config.Get("disableTlsVerification").ToBoolean();
|
|
114
|
+
}
|
|
113
115
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
116
|
+
// Proxy Server
|
|
117
|
+
if (config.Has("proxyServer") && config.Get("proxyServer").IsObject())
|
|
118
|
+
{
|
|
119
|
+
Napi::Object proxyServer = config.Get("proxyServer").As<Napi::Object>();
|
|
118
120
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
+
// IP
|
|
122
|
+
std::string ip = proxyServer.Get("ip").As<Napi::String>();
|
|
121
123
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
+
// Port
|
|
125
|
+
uint16_t port = proxyServer.Get("port").As<Napi::Number>().Uint32Value();
|
|
124
126
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
127
|
+
// Type
|
|
128
|
+
std::string strType = proxyServer.Get("type").As<Napi::String>().ToString();
|
|
129
|
+
rtc::ProxyServer::Type type = rtc::ProxyServer::Type::Http;
|
|
128
130
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
+
if (strType == "Socks5")
|
|
132
|
+
type = rtc::ProxyServer::Type::Socks5;
|
|
131
133
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
134
|
+
// Username & Password
|
|
135
|
+
std::string username = "";
|
|
136
|
+
std::string password = "";
|
|
135
137
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
138
|
+
if (proxyServer.Get("username").IsString())
|
|
139
|
+
username = proxyServer.Get("username").As<Napi::String>().ToString();
|
|
140
|
+
if (proxyServer.Get("password").IsString())
|
|
141
|
+
password = proxyServer.Get("password").As<Napi::String>().ToString();
|
|
140
142
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
+
webSocketConfig.proxyServer = rtc::ProxyServer(type, ip, port, username, password);
|
|
144
|
+
}
|
|
143
145
|
|
|
144
|
-
|
|
146
|
+
if (config.Has("protocols"))
|
|
147
|
+
{
|
|
148
|
+
if (!config.Get("protocols").IsArray())
|
|
145
149
|
{
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
Napi::TypeError::New(info.Env(), "protocols must be an array").ThrowAsJavaScriptException();
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
Napi::Array protocols = config.Get("protocols").As<Napi::Array>();
|
|
152
|
-
for (uint32_t i = 0; i < protocols.Length(); i++)
|
|
153
|
-
{
|
|
154
|
-
webSocketConfig.protocols.push_back(protocols.Get(i).ToString());
|
|
155
|
-
}
|
|
150
|
+
Napi::TypeError::New(info.Env(), "protocols must be an array").ThrowAsJavaScriptException();
|
|
151
|
+
return;
|
|
156
152
|
}
|
|
157
|
-
|
|
158
|
-
|
|
153
|
+
Napi::Array protocols = config.Get("protocols").As<Napi::Array>();
|
|
154
|
+
for (uint32_t i = 0; i < protocols.Length(); i++)
|
|
159
155
|
{
|
|
160
|
-
|
|
161
|
-
{
|
|
162
|
-
Napi::TypeError::New(info.Env(), "connectionTimeout must be a number").ThrowAsJavaScriptException();
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
webSocketConfig.connectionTimeout = std::chrono::milliseconds(config.Get("connectionTimeout").ToNumber().Int64Value());
|
|
156
|
+
webSocketConfig.protocols.push_back(protocols.Get(i).ToString());
|
|
166
157
|
}
|
|
158
|
+
}
|
|
167
159
|
|
|
168
|
-
|
|
160
|
+
if (config.Has("connectionTimeout"))
|
|
161
|
+
{
|
|
162
|
+
if (!config.Get("connectionTimeout").IsNumber())
|
|
169
163
|
{
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
Napi::TypeError::New(info.Env(), "pingInterval must be a number").ThrowAsJavaScriptException();
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
webSocketConfig.pingInterval = std::chrono::milliseconds(config.Get("pingInterval").ToNumber().Int64Value());
|
|
164
|
+
Napi::TypeError::New(info.Env(), "connectionTimeout must be a number").ThrowAsJavaScriptException();
|
|
165
|
+
return;
|
|
176
166
|
}
|
|
167
|
+
webSocketConfig.connectionTimeout =
|
|
168
|
+
std::chrono::milliseconds(config.Get("connectionTimeout").ToNumber().Int64Value());
|
|
169
|
+
}
|
|
177
170
|
|
|
178
|
-
|
|
171
|
+
if (config.Has("pingInterval"))
|
|
172
|
+
{
|
|
173
|
+
if (!config.Get("pingInterval").IsNumber())
|
|
179
174
|
{
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
Napi::TypeError::New(info.Env(), "maxOutstandingPings must be a number").ThrowAsJavaScriptException();
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
webSocketConfig.maxOutstandingPings = config.Get("maxOutstandingPings").ToNumber().Int32Value();
|
|
175
|
+
Napi::TypeError::New(info.Env(), "pingInterval must be a number").ThrowAsJavaScriptException();
|
|
176
|
+
return;
|
|
186
177
|
}
|
|
178
|
+
webSocketConfig.pingInterval = std::chrono::milliseconds(config.Get("pingInterval").ToNumber().Int64Value());
|
|
179
|
+
}
|
|
187
180
|
|
|
188
|
-
|
|
181
|
+
if (config.Has("maxOutstandingPings"))
|
|
182
|
+
{
|
|
183
|
+
if (!config.Get("maxOutstandingPings").IsNumber())
|
|
189
184
|
{
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
Napi::TypeError::New(info.Env(), "caCertificatePemFile must be a string").ThrowAsJavaScriptException();
|
|
193
|
-
return;
|
|
194
|
-
}
|
|
195
|
-
webSocketConfig.caCertificatePemFile = config.Get("caCertificatePemFile").ToString();
|
|
185
|
+
Napi::TypeError::New(info.Env(), "maxOutstandingPings must be a number").ThrowAsJavaScriptException();
|
|
186
|
+
return;
|
|
196
187
|
}
|
|
188
|
+
webSocketConfig.maxOutstandingPings = config.Get("maxOutstandingPings").ToNumber().Int32Value();
|
|
189
|
+
}
|
|
197
190
|
|
|
198
|
-
|
|
191
|
+
if (config.Has("caCertificatePemFile"))
|
|
192
|
+
{
|
|
193
|
+
if (!config.Get("caCertificatePemFile").IsString())
|
|
199
194
|
{
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
Napi::TypeError::New(info.Env(), "certificatePemFile must be a string").ThrowAsJavaScriptException();
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
|
-
webSocketConfig.certificatePemFile = config.Get("certificatePemFile").ToString();
|
|
195
|
+
Napi::TypeError::New(info.Env(), "caCertificatePemFile must be a string").ThrowAsJavaScriptException();
|
|
196
|
+
return;
|
|
206
197
|
}
|
|
198
|
+
webSocketConfig.caCertificatePemFile = config.Get("caCertificatePemFile").ToString();
|
|
199
|
+
}
|
|
207
200
|
|
|
208
|
-
|
|
201
|
+
if (config.Has("certificatePemFile"))
|
|
202
|
+
{
|
|
203
|
+
if (!config.Get("certificatePemFile").IsString())
|
|
209
204
|
{
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
Napi::TypeError::New(info.Env(), "keyPemFile must be a string").ThrowAsJavaScriptException();
|
|
213
|
-
return;
|
|
214
|
-
}
|
|
215
|
-
webSocketConfig.keyPemFile = config.Get("keyPemFile").ToString();
|
|
205
|
+
Napi::TypeError::New(info.Env(), "certificatePemFile must be a string").ThrowAsJavaScriptException();
|
|
206
|
+
return;
|
|
216
207
|
}
|
|
208
|
+
webSocketConfig.certificatePemFile = config.Get("certificatePemFile").ToString();
|
|
209
|
+
}
|
|
217
210
|
|
|
218
|
-
|
|
211
|
+
if (config.Has("keyPemFile"))
|
|
212
|
+
{
|
|
213
|
+
if (!config.Get("keyPemFile").IsString())
|
|
219
214
|
{
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
Napi::TypeError::New(info.Env(), "keyPemPass must be a string").ThrowAsJavaScriptException();
|
|
223
|
-
return;
|
|
224
|
-
}
|
|
225
|
-
webSocketConfig.keyPemPass = config.Get("keyPemPass").ToString();
|
|
215
|
+
Napi::TypeError::New(info.Env(), "keyPemFile must be a string").ThrowAsJavaScriptException();
|
|
216
|
+
return;
|
|
226
217
|
}
|
|
218
|
+
webSocketConfig.keyPemFile = config.Get("keyPemFile").ToString();
|
|
219
|
+
}
|
|
227
220
|
|
|
228
|
-
|
|
221
|
+
if (config.Has("keyPemPass"))
|
|
222
|
+
{
|
|
223
|
+
if (!config.Get("keyPemPass").IsString())
|
|
229
224
|
{
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
Napi::TypeError::New(info.Env(), "maxMessageSize must be a number").ThrowAsJavaScriptException();
|
|
233
|
-
return;
|
|
234
|
-
}
|
|
235
|
-
webSocketConfig.maxMessageSize = config.Get("maxMessageSize").ToNumber().Int32Value();
|
|
225
|
+
Napi::TypeError::New(info.Env(), "keyPemPass must be a string").ThrowAsJavaScriptException();
|
|
226
|
+
return;
|
|
236
227
|
}
|
|
228
|
+
webSocketConfig.keyPemPass = config.Get("keyPemPass").ToString();
|
|
229
|
+
}
|
|
237
230
|
|
|
238
|
-
|
|
239
|
-
|
|
231
|
+
if (config.Has("maxMessageSize"))
|
|
232
|
+
{
|
|
233
|
+
if (!config.Get("maxMessageSize").IsNumber())
|
|
240
234
|
{
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
}
|
|
244
|
-
catch (std::exception &ex)
|
|
245
|
-
{
|
|
246
|
-
Napi::Error::New(env, std::string("libdatachannel error while creating WebSocket: ") + ex.what()).ThrowAsJavaScriptException();
|
|
247
|
-
return;
|
|
235
|
+
Napi::TypeError::New(info.Env(), "maxMessageSize must be a number").ThrowAsJavaScriptException();
|
|
236
|
+
return;
|
|
248
237
|
}
|
|
238
|
+
webSocketConfig.maxMessageSize = config.Get("maxMessageSize").ToNumber().Int32Value();
|
|
239
|
+
}
|
|
249
240
|
|
|
250
|
-
|
|
241
|
+
// Create WebSocket
|
|
242
|
+
try
|
|
243
|
+
{
|
|
244
|
+
PLOG_DEBUG << "Creating a new WebSocket";
|
|
245
|
+
mWebSocketPtr = std::make_unique<rtc::WebSocket>(webSocketConfig);
|
|
246
|
+
}
|
|
247
|
+
catch (std::exception &ex)
|
|
248
|
+
{
|
|
249
|
+
Napi::Error::New(env, std::string("libdatachannel error while creating WebSocket: ") + ex.what())
|
|
250
|
+
.ThrowAsJavaScriptException();
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
251
253
|
|
|
252
|
-
|
|
253
|
-
mOnClosedCallback = std::make_unique<ThreadSafeCallback>(Napi::Function::New(info.Env(), [](const Napi::CallbackInfo &) {}));
|
|
254
|
+
PLOG_DEBUG << "WebSocket created";
|
|
254
255
|
|
|
255
|
-
|
|
256
|
+
// Closed callback must set to trigger cleanup
|
|
257
|
+
mOnClosedCallback =
|
|
258
|
+
std::make_unique<ThreadSafeCallback>(Napi::Function::New(info.Env(), [](const Napi::CallbackInfo &) {}));
|
|
259
|
+
|
|
260
|
+
instances.insert(this);
|
|
256
261
|
}
|
|
257
262
|
|
|
258
263
|
WebSocketWrapper::~WebSocketWrapper()
|
|
259
264
|
{
|
|
260
|
-
|
|
261
|
-
|
|
265
|
+
PLOG_DEBUG << "Destructor called";
|
|
266
|
+
doClose();
|
|
262
267
|
}
|
|
263
268
|
|
|
264
269
|
void WebSocketWrapper::doClose()
|
|
265
270
|
{
|
|
266
|
-
|
|
267
|
-
|
|
271
|
+
PLOG_DEBUG << "doClose() called";
|
|
272
|
+
if (mWebSocketPtr)
|
|
273
|
+
{
|
|
274
|
+
PLOG_DEBUG << "Closing...";
|
|
275
|
+
try
|
|
268
276
|
{
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
{
|
|
272
|
-
mWebSocketPtr->close();
|
|
273
|
-
mWebSocketPtr.reset();
|
|
274
|
-
}
|
|
275
|
-
catch (std::exception &ex)
|
|
276
|
-
{
|
|
277
|
-
std::cerr << std::string("libdatachannel error while closing WebSocket: ") + ex.what() << std::endl;
|
|
278
|
-
return;
|
|
279
|
-
}
|
|
277
|
+
mWebSocketPtr->close();
|
|
278
|
+
mWebSocketPtr.reset();
|
|
280
279
|
}
|
|
280
|
+
catch (std::exception &ex)
|
|
281
|
+
{
|
|
282
|
+
std::cerr << std::string("libdatachannel error while closing WebSocket: ") + ex.what() << std::endl;
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
281
286
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
287
|
+
mOnOpenCallback.reset();
|
|
288
|
+
mOnErrorCallback.reset();
|
|
289
|
+
mOnBufferedAmountLowCallback.reset();
|
|
290
|
+
mOnMessageCallback.reset();
|
|
286
291
|
}
|
|
287
292
|
|
|
288
293
|
void WebSocketWrapper::doForceClose()
|
|
289
294
|
{
|
|
290
|
-
|
|
291
|
-
|
|
295
|
+
PLOG_DEBUG << "doForceClose() called";
|
|
296
|
+
if (mWebSocketPtr)
|
|
297
|
+
{
|
|
298
|
+
PLOG_DEBUG << "Force closing...";
|
|
299
|
+
try
|
|
292
300
|
{
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
{
|
|
301
|
-
std::cerr << std::string("libdatachannel error while force closing WebSocket: ") + ex.what() << std::endl;
|
|
302
|
-
return;
|
|
303
|
-
}
|
|
301
|
+
mWebSocketPtr->forceClose();
|
|
302
|
+
mWebSocketPtr.reset();
|
|
303
|
+
}
|
|
304
|
+
catch (std::exception &ex)
|
|
305
|
+
{
|
|
306
|
+
std::cerr << std::string("libdatachannel error while force closing WebSocket: ") + ex.what() << std::endl;
|
|
307
|
+
return;
|
|
304
308
|
}
|
|
309
|
+
}
|
|
305
310
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
311
|
+
mOnOpenCallback.reset();
|
|
312
|
+
mOnErrorCallback.reset();
|
|
313
|
+
mOnBufferedAmountLowCallback.reset();
|
|
314
|
+
mOnMessageCallback.reset();
|
|
310
315
|
}
|
|
311
316
|
|
|
312
317
|
void WebSocketWrapper::doCleanup()
|
|
313
318
|
{
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
319
|
+
PLOG_DEBUG << "doCleanup() called";
|
|
320
|
+
mOnClosedCallback.reset();
|
|
321
|
+
instances.erase(this);
|
|
317
322
|
}
|
|
318
323
|
|
|
319
324
|
void WebSocketWrapper::open(const Napi::CallbackInfo &info)
|
|
320
325
|
{
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
326
|
+
PLOG_DEBUG << "open() called";
|
|
327
|
+
Napi::Env env = info.Env();
|
|
328
|
+
|
|
329
|
+
if (!mWebSocketPtr)
|
|
330
|
+
{
|
|
331
|
+
Napi::Error::New(env, "open() called on destroyed WebSocket").ThrowAsJavaScriptException();
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
if (info.Length() < 1 || !info[0].IsString())
|
|
335
|
+
{
|
|
336
|
+
Napi::TypeError::New(env, "url must be string").ThrowAsJavaScriptException();
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
try
|
|
341
|
+
{
|
|
342
|
+
mWebSocketPtr->open(info[0].As<Napi::String>().ToString());
|
|
343
|
+
}
|
|
344
|
+
catch (std::exception &ex)
|
|
345
|
+
{
|
|
346
|
+
Napi::Error::New(env, std::string("libdatachannel error while opening WebSocket: ") + ex.what())
|
|
347
|
+
.ThrowAsJavaScriptException();
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
344
350
|
}
|
|
345
351
|
|
|
346
352
|
void WebSocketWrapper::close(const Napi::CallbackInfo &info)
|
|
347
353
|
{
|
|
348
|
-
|
|
349
|
-
|
|
354
|
+
PLOG_DEBUG << "close() called";
|
|
355
|
+
doClose();
|
|
350
356
|
}
|
|
351
357
|
|
|
352
358
|
void WebSocketWrapper::forceClose(const Napi::CallbackInfo &info)
|
|
353
359
|
{
|
|
354
|
-
|
|
355
|
-
|
|
360
|
+
PLOG_DEBUG << "forceClose() called";
|
|
361
|
+
doForceClose();
|
|
356
362
|
}
|
|
357
363
|
|
|
358
364
|
Napi::Value WebSocketWrapper::sendMessage(const Napi::CallbackInfo &info)
|
|
359
365
|
{
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
366
|
+
PLOG_DEBUG << "sendMessage() called";
|
|
367
|
+
if (!mWebSocketPtr)
|
|
368
|
+
{
|
|
369
|
+
Napi::Error::New(info.Env(), "sendMessage() called on destroyed channel").ThrowAsJavaScriptException();
|
|
370
|
+
return info.Env().Null();
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
Napi::Env env = info.Env();
|
|
374
|
+
int length = info.Length();
|
|
375
|
+
|
|
376
|
+
// Allow call with NULL
|
|
377
|
+
if (length < 1 || (!info[0].IsString() && !info[0].IsNull()))
|
|
378
|
+
{
|
|
379
|
+
Napi::TypeError::New(env, "String or Null expected").ThrowAsJavaScriptException();
|
|
380
|
+
return info.Env().Null();
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
try
|
|
384
|
+
{
|
|
385
|
+
return Napi::Boolean::New(info.Env(), mWebSocketPtr->send(info[0].As<Napi::String>().ToString()));
|
|
386
|
+
}
|
|
387
|
+
catch (std::exception &ex)
|
|
388
|
+
{
|
|
389
|
+
Napi::Error::New(env, std::string("libdatachannel error while sending data channel message: ") + ex.what())
|
|
390
|
+
.ThrowAsJavaScriptException();
|
|
391
|
+
return Napi::Boolean::New(info.Env(), false);
|
|
392
|
+
}
|
|
386
393
|
}
|
|
387
394
|
|
|
388
395
|
Napi::Value WebSocketWrapper::sendMessageBinary(const Napi::CallbackInfo &info)
|
|
389
396
|
{
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
397
|
+
PLOG_DEBUG << "sendMessageBinary() called";
|
|
398
|
+
if (!mWebSocketPtr)
|
|
399
|
+
{
|
|
400
|
+
Napi::Error::New(info.Env(), "sendMessagBinary() called on destroyed channel").ThrowAsJavaScriptException();
|
|
401
|
+
return info.Env().Null();
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
Napi::Env env = info.Env();
|
|
405
|
+
int length = info.Length();
|
|
406
|
+
|
|
407
|
+
if (length < 1 || !info[0].IsBuffer())
|
|
408
|
+
{
|
|
409
|
+
Napi::TypeError::New(env, "Buffer expected").ThrowAsJavaScriptException();
|
|
410
|
+
return info.Env().Null();
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
try
|
|
414
|
+
{
|
|
415
|
+
Napi::Uint8Array buffer = info[0].As<Napi::Uint8Array>();
|
|
416
|
+
return Napi::Boolean::New(info.Env(), mWebSocketPtr->send((std::byte *)buffer.Data(), buffer.ByteLength()));
|
|
417
|
+
}
|
|
418
|
+
catch (std::exception &ex)
|
|
419
|
+
{
|
|
420
|
+
Napi::Error::New(env, std::string("libdatachannel error while sending data channel message: ") + ex.what())
|
|
421
|
+
.ThrowAsJavaScriptException();
|
|
422
|
+
return Napi::Boolean::New(info.Env(), false);
|
|
423
|
+
}
|
|
416
424
|
}
|
|
417
425
|
|
|
418
426
|
Napi::Value WebSocketWrapper::isOpen(const Napi::CallbackInfo &info)
|
|
419
427
|
{
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
428
|
+
PLOG_DEBUG << "isOpen() called";
|
|
429
|
+
Napi::Env env = info.Env();
|
|
430
|
+
|
|
431
|
+
if (!mWebSocketPtr)
|
|
432
|
+
{
|
|
433
|
+
return Napi::Boolean::New(info.Env(), false);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
try
|
|
437
|
+
{
|
|
438
|
+
return Napi::Boolean::New(info.Env(), mWebSocketPtr->isOpen());
|
|
439
|
+
}
|
|
440
|
+
catch (std::exception &ex)
|
|
441
|
+
{
|
|
442
|
+
Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
|
|
443
|
+
return Napi::Boolean::New(info.Env(), false);
|
|
444
|
+
}
|
|
437
445
|
}
|
|
438
446
|
|
|
439
447
|
Napi::Value WebSocketWrapper::bufferedAmount(const Napi::CallbackInfo &info)
|
|
440
448
|
{
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
449
|
+
PLOG_DEBUG << "bufferedAmount() called";
|
|
450
|
+
Napi::Env env = info.Env();
|
|
451
|
+
|
|
452
|
+
if (!mWebSocketPtr)
|
|
453
|
+
{
|
|
454
|
+
return Napi::Number::New(info.Env(), 0);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
try
|
|
458
|
+
{
|
|
459
|
+
return Napi::Number::New(info.Env(), mWebSocketPtr->bufferedAmount());
|
|
460
|
+
}
|
|
461
|
+
catch (std::exception &ex)
|
|
462
|
+
{
|
|
463
|
+
Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
|
|
464
|
+
return Napi::Number::New(info.Env(), 0);
|
|
465
|
+
}
|
|
458
466
|
}
|
|
459
467
|
|
|
460
468
|
Napi::Value WebSocketWrapper::maxMessageSize(const Napi::CallbackInfo &info)
|
|
461
469
|
{
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
470
|
+
PLOG_DEBUG << "maxMessageSize() called";
|
|
471
|
+
Napi::Env env = info.Env();
|
|
472
|
+
|
|
473
|
+
if (!mWebSocketPtr)
|
|
474
|
+
{
|
|
475
|
+
return Napi::Number::New(info.Env(), 0);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
try
|
|
479
|
+
{
|
|
480
|
+
return Napi::Number::New(info.Env(), mWebSocketPtr->maxMessageSize());
|
|
481
|
+
}
|
|
482
|
+
catch (std::exception &ex)
|
|
483
|
+
{
|
|
484
|
+
Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
|
|
485
|
+
return Napi::Number::New(info.Env(), 0);
|
|
486
|
+
}
|
|
479
487
|
}
|
|
480
488
|
|
|
481
489
|
Napi::Value WebSocketWrapper::remoteAddress(const Napi::CallbackInfo &info)
|
|
482
490
|
{
|
|
483
|
-
|
|
484
|
-
|
|
491
|
+
PLOG_DEBUG << "remoteAddress() called";
|
|
492
|
+
Napi::Env env = info.Env();
|
|
485
493
|
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
494
|
+
if (!mWebSocketPtr)
|
|
495
|
+
{
|
|
496
|
+
return env.Undefined();
|
|
497
|
+
}
|
|
490
498
|
|
|
491
|
-
|
|
499
|
+
try
|
|
500
|
+
{
|
|
501
|
+
auto address = mWebSocketPtr->remoteAddress();
|
|
502
|
+
if (address.has_value())
|
|
492
503
|
{
|
|
493
|
-
|
|
494
|
-
if (address.has_value())
|
|
495
|
-
{
|
|
496
|
-
return Napi::String::New(info.Env(), address.value());
|
|
497
|
-
}
|
|
498
|
-
else
|
|
499
|
-
{
|
|
500
|
-
return env.Undefined();
|
|
501
|
-
}
|
|
504
|
+
return Napi::String::New(info.Env(), address.value());
|
|
502
505
|
}
|
|
503
|
-
|
|
506
|
+
else
|
|
504
507
|
{
|
|
505
|
-
|
|
506
|
-
return env.Undefined();
|
|
508
|
+
return env.Undefined();
|
|
507
509
|
}
|
|
510
|
+
}
|
|
511
|
+
catch (std::exception &ex)
|
|
512
|
+
{
|
|
513
|
+
Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
|
|
514
|
+
return env.Undefined();
|
|
515
|
+
}
|
|
508
516
|
}
|
|
509
517
|
|
|
510
518
|
Napi::Value WebSocketWrapper::path(const Napi::CallbackInfo &info)
|
|
511
519
|
{
|
|
512
|
-
|
|
513
|
-
|
|
520
|
+
PLOG_DEBUG << "path() called";
|
|
521
|
+
Napi::Env env = info.Env();
|
|
514
522
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
523
|
+
if (!mWebSocketPtr)
|
|
524
|
+
{
|
|
525
|
+
return env.Undefined();
|
|
526
|
+
}
|
|
519
527
|
|
|
520
|
-
|
|
528
|
+
try
|
|
529
|
+
{
|
|
530
|
+
auto path = mWebSocketPtr->path();
|
|
531
|
+
if (path.has_value())
|
|
521
532
|
{
|
|
522
|
-
|
|
523
|
-
if (path.has_value())
|
|
524
|
-
{
|
|
525
|
-
return Napi::String::New(info.Env(), path.value());
|
|
526
|
-
}
|
|
527
|
-
else
|
|
528
|
-
{
|
|
529
|
-
return env.Undefined();
|
|
530
|
-
}
|
|
533
|
+
return Napi::String::New(info.Env(), path.value());
|
|
531
534
|
}
|
|
532
|
-
|
|
535
|
+
else
|
|
533
536
|
{
|
|
534
|
-
|
|
535
|
-
return env.Undefined();
|
|
537
|
+
return env.Undefined();
|
|
536
538
|
}
|
|
539
|
+
}
|
|
540
|
+
catch (std::exception &ex)
|
|
541
|
+
{
|
|
542
|
+
Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
|
|
543
|
+
return env.Undefined();
|
|
544
|
+
}
|
|
537
545
|
}
|
|
538
546
|
|
|
539
547
|
void WebSocketWrapper::setBufferedAmountLowThreshold(const Napi::CallbackInfo &info)
|
|
540
548
|
{
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
549
|
+
PLOG_DEBUG << "setBufferedAmountLowThreshold() called";
|
|
550
|
+
if (!mWebSocketPtr)
|
|
551
|
+
{
|
|
552
|
+
Napi::Error::New(info.Env(), "setBufferedAmountLowThreshold() called on destroyed channel")
|
|
553
|
+
.ThrowAsJavaScriptException();
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
Napi::Env env = info.Env();
|
|
558
|
+
int length = info.Length();
|
|
559
|
+
|
|
560
|
+
if (length < 1 || !info[0].IsNumber())
|
|
561
|
+
{
|
|
562
|
+
Napi::TypeError::New(env, "Number expected").ThrowAsJavaScriptException();
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
try
|
|
567
|
+
{
|
|
568
|
+
mWebSocketPtr->setBufferedAmountLowThreshold(info[0].ToNumber().Uint32Value());
|
|
569
|
+
}
|
|
570
|
+
catch (std::exception &ex)
|
|
571
|
+
{
|
|
572
|
+
Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
566
575
|
}
|
|
567
576
|
|
|
568
577
|
void WebSocketWrapper::onOpen(const Napi::CallbackInfo &info)
|
|
569
578
|
{
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
579
|
+
PLOG_DEBUG << "new onOpen() called";
|
|
580
|
+
if (!mWebSocketPtr)
|
|
581
|
+
{
|
|
582
|
+
Napi::Error::New(info.Env(), "onOpen() called on destroyed channel").ThrowAsJavaScriptException();
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
Napi::Env env = info.Env();
|
|
587
|
+
int length = info.Length();
|
|
588
|
+
|
|
589
|
+
if (length < 1 || !info[0].IsFunction())
|
|
590
|
+
{
|
|
591
|
+
Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
|
|
592
|
+
return;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
// Callback
|
|
596
|
+
mOnOpenCallback = std::make_unique<ThreadSafeCallback>(info[0].As<Napi::Function>());
|
|
597
|
+
|
|
598
|
+
mWebSocketPtr->onOpen(
|
|
599
|
+
[&]()
|
|
600
|
+
{
|
|
601
|
+
PLOG_DEBUG << "onOpen cb received from rtc";
|
|
602
|
+
|
|
603
|
+
if (mOnOpenCallback)
|
|
604
|
+
mOnOpenCallback->call(
|
|
605
|
+
[this](Napi::Env env, std::vector<napi_value> &args)
|
|
606
|
+
{
|
|
607
|
+
PLOG_DEBUG << "mOnOpenCallback call(1)";
|
|
608
|
+
// Check the WebSocket is not closed
|
|
609
|
+
if (instances.find(this) == instances.end())
|
|
610
|
+
{
|
|
611
|
+
PLOG_DEBUG << "WebSocket not found in instances";
|
|
612
|
+
throw ThreadSafeCallback::CancelException();
|
|
613
|
+
}
|
|
585
614
|
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
if (mOnOpenCallback)
|
|
594
|
-
mOnOpenCallback->call([this](Napi::Env env, std::vector<napi_value> &args)
|
|
595
|
-
{
|
|
596
|
-
PLOG_DEBUG << "mOnOpenCallback call(1)";
|
|
597
|
-
// Check the WebSocket is not closed
|
|
598
|
-
if(instances.find(this) == instances.end())
|
|
599
|
-
{
|
|
600
|
-
PLOG_DEBUG << "WebSocket not found in instances";
|
|
601
|
-
throw ThreadSafeCallback::CancelException();
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
// This will run in main thread and needs to construct the
|
|
606
|
-
// arguments for the call
|
|
607
|
-
args = {};
|
|
608
|
-
PLOG_DEBUG << "mOnOpenCallback call(2)"; }); });
|
|
615
|
+
// This will run in main thread and needs to construct the
|
|
616
|
+
// arguments for the call
|
|
617
|
+
args = {};
|
|
618
|
+
PLOG_DEBUG << "mOnOpenCallback call(2)";
|
|
619
|
+
});
|
|
620
|
+
});
|
|
609
621
|
}
|
|
610
622
|
|
|
611
623
|
void WebSocketWrapper::onClosed(const Napi::CallbackInfo &info)
|
|
612
624
|
{
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
625
|
+
PLOG_DEBUG << "onClosed() called";
|
|
626
|
+
if (!mWebSocketPtr)
|
|
627
|
+
{
|
|
628
|
+
Napi::Error::New(info.Env(), "onClosed() called on destroyed WebSocket").ThrowAsJavaScriptException();
|
|
629
|
+
return;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
Napi::Env env = info.Env();
|
|
633
|
+
int length = info.Length();
|
|
634
|
+
|
|
635
|
+
if (length < 1 || !info[0].IsFunction())
|
|
636
|
+
{
|
|
637
|
+
Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
|
|
638
|
+
return;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
// Callback
|
|
642
|
+
mOnClosedCallback = std::make_unique<ThreadSafeCallback>(info[0].As<Napi::Function>());
|
|
643
|
+
|
|
644
|
+
mWebSocketPtr->onClosed(
|
|
645
|
+
[&]()
|
|
646
|
+
{
|
|
647
|
+
PLOG_DEBUG << "onClosed cb received from rtc";
|
|
648
|
+
if (mOnClosedCallback)
|
|
649
|
+
mOnClosedCallback->call(
|
|
650
|
+
[this](Napi::Env env, std::vector<napi_value> &args)
|
|
651
|
+
{
|
|
652
|
+
PLOG_DEBUG << "mOnClosedCallback call";
|
|
653
|
+
// Do not check if the data channel has been closed here
|
|
654
|
+
|
|
655
|
+
// This will run in main thread and needs to construct the
|
|
656
|
+
// arguments for the call
|
|
657
|
+
args = {};
|
|
658
|
+
},
|
|
659
|
+
[this] { doCleanup(); });
|
|
660
|
+
});
|
|
646
661
|
}
|
|
647
662
|
|
|
648
663
|
void WebSocketWrapper::onError(const Napi::CallbackInfo &info)
|
|
649
664
|
{
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
665
|
+
PLOG_DEBUG << "onError() called";
|
|
666
|
+
if (!mWebSocketPtr)
|
|
667
|
+
{
|
|
668
|
+
Napi::Error::New(info.Env(), "onError() called on destroyed channel").ThrowAsJavaScriptException();
|
|
669
|
+
return;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
Napi::Env env = info.Env();
|
|
673
|
+
int length = info.Length();
|
|
674
|
+
|
|
675
|
+
if (length < 1 || !info[0].IsFunction())
|
|
676
|
+
{
|
|
677
|
+
Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
|
|
678
|
+
return;
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
// Callback
|
|
682
|
+
mOnErrorCallback = std::make_unique<ThreadSafeCallback>(info[0].As<Napi::Function>());
|
|
683
|
+
|
|
684
|
+
mWebSocketPtr->onError(
|
|
685
|
+
[&](std::string error)
|
|
686
|
+
{
|
|
687
|
+
PLOG_DEBUG << "onError cb received from rtc";
|
|
688
|
+
if (mOnErrorCallback)
|
|
689
|
+
mOnErrorCallback->call(
|
|
690
|
+
[this, error = std::move(error)](Napi::Env env, std::vector<napi_value> &args)
|
|
691
|
+
{
|
|
692
|
+
PLOG_DEBUG << "mOnErrorCallback call(1)";
|
|
693
|
+
// Check the data channel is not closed
|
|
694
|
+
if (instances.find(this) == instances.end())
|
|
695
|
+
throw ThreadSafeCallback::CancelException();
|
|
696
|
+
|
|
697
|
+
// This will run in main thread and needs to construct the
|
|
698
|
+
// arguments for the call
|
|
699
|
+
args = {Napi::String::New(env, error)};
|
|
700
|
+
PLOG_DEBUG << "mOnErrorCallback call(2)";
|
|
701
|
+
});
|
|
702
|
+
});
|
|
684
703
|
}
|
|
685
704
|
|
|
686
705
|
void WebSocketWrapper::onBufferedAmountLow(const Napi::CallbackInfo &info)
|
|
687
706
|
{
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
707
|
+
PLOG_DEBUG << "onBufferedAmountLow() called";
|
|
708
|
+
if (!mWebSocketPtr)
|
|
709
|
+
{
|
|
710
|
+
Napi::Error::New(info.Env(), "onBufferedAmountLow() called on destroyed channel").ThrowAsJavaScriptException();
|
|
711
|
+
return;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
Napi::Env env = info.Env();
|
|
715
|
+
int length = info.Length();
|
|
716
|
+
|
|
717
|
+
if (length < 1 || !info[0].IsFunction())
|
|
718
|
+
{
|
|
719
|
+
Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
|
|
720
|
+
return;
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
// Callback
|
|
724
|
+
mOnBufferedAmountLowCallback = std::make_unique<ThreadSafeCallback>(info[0].As<Napi::Function>());
|
|
725
|
+
|
|
726
|
+
mWebSocketPtr->onBufferedAmountLow(
|
|
727
|
+
[&]()
|
|
728
|
+
{
|
|
729
|
+
PLOG_DEBUG << "onBufferedAmountLow cb received from rtc";
|
|
730
|
+
if (mOnBufferedAmountLowCallback)
|
|
731
|
+
mOnBufferedAmountLowCallback->call(
|
|
732
|
+
[this](Napi::Env env, std::vector<napi_value> &args)
|
|
733
|
+
{
|
|
734
|
+
PLOG_DEBUG << "mOnBufferedAmountLowCallback call(1)";
|
|
735
|
+
// Check the data channel is not closed
|
|
736
|
+
if (instances.find(this) == instances.end())
|
|
737
|
+
throw ThreadSafeCallback::CancelException();
|
|
738
|
+
|
|
739
|
+
// This will run in main thread and needs to construct the
|
|
740
|
+
// arguments for the call
|
|
741
|
+
args = {};
|
|
742
|
+
PLOG_DEBUG << "mOnBufferedAmountLowCallback call(2)";
|
|
743
|
+
});
|
|
744
|
+
});
|
|
722
745
|
}
|
|
723
746
|
|
|
724
747
|
void WebSocketWrapper::onMessage(const Napi::CallbackInfo &info)
|
|
725
748
|
{
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
749
|
+
PLOG_DEBUG << "onMessage() called";
|
|
750
|
+
if (!mWebSocketPtr)
|
|
751
|
+
{
|
|
752
|
+
Napi::Error::New(info.Env(), "onMessage() called on destroyed channel").ThrowAsJavaScriptException();
|
|
753
|
+
return;
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
Napi::Env env = info.Env();
|
|
757
|
+
int length = info.Length();
|
|
758
|
+
|
|
759
|
+
if (length < 1 || !info[0].IsFunction())
|
|
760
|
+
{
|
|
761
|
+
Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
|
|
762
|
+
return;
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
// Callback
|
|
766
|
+
mOnMessageCallback = std::make_unique<ThreadSafeCallback>(info[0].As<Napi::Function>());
|
|
767
|
+
|
|
768
|
+
PLOG_DEBUG << "setting onMessage cb on mWebSocketPtr";
|
|
769
|
+
mWebSocketPtr->onMessage(
|
|
770
|
+
[&](std::variant<rtc::binary, std::string> message)
|
|
771
|
+
{
|
|
772
|
+
PLOG_DEBUG << "onMessage cb received from rtc";
|
|
773
|
+
if (mOnMessageCallback)
|
|
774
|
+
mOnMessageCallback->call(
|
|
775
|
+
[this, message = std::move(message)](Napi::Env env, std::vector<napi_value> &args)
|
|
776
|
+
{
|
|
777
|
+
PLOG_DEBUG << "mOnMessageCallback call(1)";
|
|
778
|
+
// Check the data channel is not closed
|
|
779
|
+
if (instances.find(this) == instances.end())
|
|
780
|
+
throw ThreadSafeCallback::CancelException();
|
|
781
|
+
|
|
782
|
+
// This will run in main thread and needs to construct the
|
|
783
|
+
// arguments for the call
|
|
784
|
+
if (std::holds_alternative<std::string>(message))
|
|
785
|
+
{
|
|
786
|
+
args = {Napi::String::New(env, std::get<std::string>(message))};
|
|
787
|
+
}
|
|
788
|
+
else
|
|
789
|
+
{
|
|
790
|
+
auto bin = std::get<rtc::binary>(std::move(message));
|
|
791
|
+
args = {Napi::Buffer<std::byte>::Copy(env, bin.data(), bin.size())};
|
|
792
|
+
}
|
|
793
|
+
PLOG_DEBUG << "mOnMessageCallback call(2)";
|
|
794
|
+
});
|
|
795
|
+
});
|
|
769
796
|
}
|