@lng2004/node-datachannel 0.31.0-20251228
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/.editorconfig +12 -0
- package/.eslintignore +8 -0
- package/.eslintrc.json +27 -0
- package/.gitmodules +3 -0
- package/.prettierignore +7 -0
- package/.prettierrc +13 -0
- package/API.md +247 -0
- package/BULDING.md +33 -0
- package/CMakeLists.txt +134 -0
- package/LICENSE +373 -0
- package/README.md +130 -0
- package/dist/cjs/index.cjs +11 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/cjs/lib/datachannel-stream.cjs +101 -0
- package/dist/cjs/lib/datachannel-stream.cjs.map +1 -0
- package/dist/cjs/lib/index.cjs +88 -0
- package/dist/cjs/lib/index.cjs.map +1 -0
- package/dist/cjs/lib/node-datachannel.cjs +8 -0
- package/dist/cjs/lib/node-datachannel.cjs.map +1 -0
- package/dist/cjs/lib/websocket-server.cjs +45 -0
- package/dist/cjs/lib/websocket-server.cjs.map +1 -0
- package/dist/cjs/lib/websocket.cjs +8 -0
- package/dist/cjs/lib/websocket.cjs.map +1 -0
- package/dist/cjs/polyfill/Events.cjs +86 -0
- package/dist/cjs/polyfill/Events.cjs.map +1 -0
- package/dist/cjs/polyfill/Exception.cjs +34 -0
- package/dist/cjs/polyfill/Exception.cjs.map +1 -0
- package/dist/cjs/polyfill/RTCCertificate.cjs +34 -0
- package/dist/cjs/polyfill/RTCCertificate.cjs.map +1 -0
- package/dist/cjs/polyfill/RTCDataChannel.cjs +214 -0
- package/dist/cjs/polyfill/RTCDataChannel.cjs.map +1 -0
- package/dist/cjs/polyfill/RTCDtlsTransport.cjs +53 -0
- package/dist/cjs/polyfill/RTCDtlsTransport.cjs.map +1 -0
- package/dist/cjs/polyfill/RTCError.cjs +83 -0
- package/dist/cjs/polyfill/RTCError.cjs.map +1 -0
- package/dist/cjs/polyfill/RTCIceCandidate.cjs +132 -0
- package/dist/cjs/polyfill/RTCIceCandidate.cjs.map +1 -0
- package/dist/cjs/polyfill/RTCIceTransport.cjs +94 -0
- package/dist/cjs/polyfill/RTCIceTransport.cjs.map +1 -0
- package/dist/cjs/polyfill/RTCPeerConnection.cjs +434 -0
- package/dist/cjs/polyfill/RTCPeerConnection.cjs.map +1 -0
- package/dist/cjs/polyfill/RTCSctpTransport.cjs +59 -0
- package/dist/cjs/polyfill/RTCSctpTransport.cjs.map +1 -0
- package/dist/cjs/polyfill/RTCSessionDescription.cjs +45 -0
- package/dist/cjs/polyfill/RTCSessionDescription.cjs.map +1 -0
- package/dist/cjs/polyfill/index.cjs +42 -0
- package/dist/cjs/polyfill/index.cjs.map +1 -0
- package/dist/esm/index.mjs +8 -0
- package/dist/esm/index.mjs.map +1 -0
- package/dist/esm/lib/datachannel-stream.mjs +78 -0
- package/dist/esm/lib/datachannel-stream.mjs.map +1 -0
- package/dist/esm/lib/index.mjs +62 -0
- package/dist/esm/lib/index.mjs.map +1 -0
- package/dist/esm/lib/node-datachannel.mjs +12 -0
- package/dist/esm/lib/node-datachannel.mjs.map +1 -0
- package/dist/esm/lib/websocket-server.mjs +43 -0
- package/dist/esm/lib/websocket-server.mjs.map +1 -0
- package/dist/esm/lib/websocket.mjs +6 -0
- package/dist/esm/lib/websocket.mjs.map +1 -0
- package/dist/esm/polyfill/Events.mjs +82 -0
- package/dist/esm/polyfill/Events.mjs.map +1 -0
- package/dist/esm/polyfill/Exception.mjs +28 -0
- package/dist/esm/polyfill/Exception.mjs.map +1 -0
- package/dist/esm/polyfill/RTCCertificate.mjs +30 -0
- package/dist/esm/polyfill/RTCCertificate.mjs.map +1 -0
- package/dist/esm/polyfill/RTCDataChannel.mjs +210 -0
- package/dist/esm/polyfill/RTCDataChannel.mjs.map +1 -0
- package/dist/esm/polyfill/RTCDtlsTransport.mjs +49 -0
- package/dist/esm/polyfill/RTCDtlsTransport.mjs.map +1 -0
- package/dist/esm/polyfill/RTCError.mjs +79 -0
- package/dist/esm/polyfill/RTCError.mjs.map +1 -0
- package/dist/esm/polyfill/RTCIceCandidate.mjs +128 -0
- package/dist/esm/polyfill/RTCIceCandidate.mjs.map +1 -0
- package/dist/esm/polyfill/RTCIceTransport.mjs +89 -0
- package/dist/esm/polyfill/RTCIceTransport.mjs.map +1 -0
- package/dist/esm/polyfill/RTCPeerConnection.mjs +430 -0
- package/dist/esm/polyfill/RTCPeerConnection.mjs.map +1 -0
- package/dist/esm/polyfill/RTCSctpTransport.mjs +55 -0
- package/dist/esm/polyfill/RTCSctpTransport.mjs.map +1 -0
- package/dist/esm/polyfill/RTCSessionDescription.mjs +41 -0
- package/dist/esm/polyfill/RTCSessionDescription.mjs.map +1 -0
- package/dist/esm/polyfill/index.mjs +27 -0
- package/dist/esm/polyfill/index.mjs.map +1 -0
- package/dist/types/lib/datachannel-stream.d.ts +24 -0
- package/dist/types/lib/index.d.ts +235 -0
- package/dist/types/lib/types.d.ts +118 -0
- package/dist/types/lib/websocket-server.d.ts +13 -0
- package/dist/types/lib/websocket.d.ts +25 -0
- package/dist/types/polyfill/Events.d.ts +15 -0
- package/dist/types/polyfill/RTCCertificate.d.ts +9 -0
- package/dist/types/polyfill/RTCDataChannel.d.ts +29 -0
- package/dist/types/polyfill/RTCDtlsTransport.d.ts +15 -0
- package/dist/types/polyfill/RTCError.d.ts +17 -0
- package/dist/types/polyfill/RTCIceCandidate.d.ts +21 -0
- package/dist/types/polyfill/RTCIceTransport.d.ts +30 -0
- package/dist/types/polyfill/RTCPeerConnection.d.ts +64 -0
- package/dist/types/polyfill/RTCSctpTransport.d.ts +15 -0
- package/dist/types/polyfill/RTCSessionDescription.d.ts +10 -0
- package/dist/types/polyfill/index.d.ts +26 -0
- package/jest.config.ts +14 -0
- package/package.json +121 -0
- package/rollup.config.mjs +72 -0
- package/src/cpp/data-channel-wrapper.cpp +530 -0
- package/src/cpp/data-channel-wrapper.h +63 -0
- package/src/cpp/ice-udp-mux-listener-wrapper.cpp +157 -0
- package/src/cpp/ice-udp-mux-listener-wrapper.h +43 -0
- package/src/cpp/main.cpp +58 -0
- package/src/cpp/media-audio-wrapper.cpp +457 -0
- package/src/cpp/media-audio-wrapper.h +52 -0
- 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 +43 -0
- package/src/cpp/media-direction.h +10 -0
- 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 +31 -0
- package/src/cpp/media-mediahandler-helper.h +11 -0
- package/src/cpp/media-pacinghandler-wrapper.cpp +79 -0
- package/src/cpp/media-pacinghandler-wrapper.h +28 -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 +57 -0
- package/src/cpp/media-rtcpreceivingsession-wrapper.h +28 -0
- 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 +458 -0
- package/src/cpp/media-track-wrapper.h +61 -0
- package/src/cpp/media-video-wrapper.cpp +526 -0
- package/src/cpp/media-video-wrapper.h +56 -0
- package/src/cpp/peer-connection-wrapper.cpp +1298 -0
- package/src/cpp/peer-connection-wrapper.h +89 -0
- package/src/cpp/rtc-wrapper.cpp +205 -0
- package/src/cpp/rtc-wrapper.h +24 -0
- package/src/cpp/thread-safe-callback.cpp +57 -0
- package/src/cpp/thread-safe-callback.h +47 -0
- package/src/cpp/web-socket-server-wrapper.cpp +275 -0
- package/src/cpp/web-socket-server-wrapper.h +41 -0
- package/src/cpp/web-socket-wrapper.cpp +796 -0
- package/src/cpp/web-socket-wrapper.h +63 -0
- package/src/index.ts +9 -0
- package/src/lib/datachannel-stream.ts +100 -0
- package/src/lib/index.ts +283 -0
- package/src/lib/node-datachannel.ts +3 -0
- package/src/lib/types.ts +168 -0
- package/src/lib/websocket-server.ts +37 -0
- package/src/lib/websocket.ts +26 -0
- package/src/polyfill/Events.ts +82 -0
- package/src/polyfill/Exception.ts +37 -0
- package/src/polyfill/README.md +41 -0
- package/src/polyfill/RTCCertificate.ts +21 -0
- package/src/polyfill/RTCDataChannel.ts +225 -0
- package/src/polyfill/RTCDtlsTransport.ts +46 -0
- package/src/polyfill/RTCError.ts +78 -0
- package/src/polyfill/RTCIceCandidate.ts +128 -0
- package/src/polyfill/RTCIceTransport.ts +90 -0
- package/src/polyfill/RTCPeerConnection.ts +527 -0
- package/src/polyfill/RTCSctpTransport.ts +51 -0
- package/src/polyfill/RTCSessionDescription.ts +41 -0
- package/src/polyfill/index.ts +38 -0
- package/tsconfig.json +21 -0
|
@@ -0,0 +1,796 @@
|
|
|
1
|
+
#include "web-socket-wrapper.h"
|
|
2
|
+
|
|
3
|
+
#include "plog/Log.h"
|
|
4
|
+
|
|
5
|
+
Napi::FunctionReference WebSocketWrapper::constructor = Napi::FunctionReference();
|
|
6
|
+
std::unordered_set<WebSocketWrapper *> WebSocketWrapper::instances;
|
|
7
|
+
|
|
8
|
+
void WebSocketWrapper::CloseAll()
|
|
9
|
+
{
|
|
10
|
+
PLOG_DEBUG << "CloseAll() called";
|
|
11
|
+
auto copy(instances);
|
|
12
|
+
for (auto inst : copy)
|
|
13
|
+
inst->doClose();
|
|
14
|
+
}
|
|
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
|
+
|
|
24
|
+
Napi::Object WebSocketWrapper::Init(Napi::Env env, Napi::Object exports)
|
|
25
|
+
{
|
|
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;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
WebSocketWrapper::WebSocketWrapper(const Napi::CallbackInfo &info) : Napi::ObjectWrap<WebSocketWrapper>(info)
|
|
61
|
+
{
|
|
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);
|
|
71
|
+
|
|
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
|
+
}
|
|
77
|
+
|
|
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>();
|
|
85
|
+
}
|
|
86
|
+
catch (std::exception &ex)
|
|
87
|
+
{
|
|
88
|
+
Napi::Error::New(env, std::string("libdatachannel error while creating WebSocket without config: ") + ex.what())
|
|
89
|
+
.ThrowAsJavaScriptException();
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
instances.insert(this);
|
|
93
|
+
|
|
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
|
+
}
|
|
99
|
+
|
|
100
|
+
// Create WebSocket with config
|
|
101
|
+
PLOG_DEBUG << "Creating a new WebSocket with config";
|
|
102
|
+
|
|
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())
|
|
109
|
+
{
|
|
110
|
+
Napi::TypeError::New(info.Env(), "disableTlsVerification must be boolean").ThrowAsJavaScriptException();
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
webSocketConfig.disableTlsVerification = config.Get("disableTlsVerification").ToBoolean();
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Proxy Server
|
|
117
|
+
if (config.Has("proxyServer") && config.Get("proxyServer").IsObject())
|
|
118
|
+
{
|
|
119
|
+
Napi::Object proxyServer = config.Get("proxyServer").As<Napi::Object>();
|
|
120
|
+
|
|
121
|
+
// IP
|
|
122
|
+
std::string ip = proxyServer.Get("ip").As<Napi::String>();
|
|
123
|
+
|
|
124
|
+
// Port
|
|
125
|
+
uint16_t port = proxyServer.Get("port").As<Napi::Number>().Uint32Value();
|
|
126
|
+
|
|
127
|
+
// Type
|
|
128
|
+
std::string strType = proxyServer.Get("type").As<Napi::String>().ToString();
|
|
129
|
+
rtc::ProxyServer::Type type = rtc::ProxyServer::Type::Http;
|
|
130
|
+
|
|
131
|
+
if (strType == "Socks5")
|
|
132
|
+
type = rtc::ProxyServer::Type::Socks5;
|
|
133
|
+
|
|
134
|
+
// Username & Password
|
|
135
|
+
std::string username = "";
|
|
136
|
+
std::string password = "";
|
|
137
|
+
|
|
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();
|
|
142
|
+
|
|
143
|
+
webSocketConfig.proxyServer = rtc::ProxyServer(type, ip, port, username, password);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (config.Has("protocols"))
|
|
147
|
+
{
|
|
148
|
+
if (!config.Get("protocols").IsArray())
|
|
149
|
+
{
|
|
150
|
+
Napi::TypeError::New(info.Env(), "protocols must be an array").ThrowAsJavaScriptException();
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
Napi::Array protocols = config.Get("protocols").As<Napi::Array>();
|
|
154
|
+
for (uint32_t i = 0; i < protocols.Length(); i++)
|
|
155
|
+
{
|
|
156
|
+
webSocketConfig.protocols.push_back(protocols.Get(i).ToString());
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (config.Has("connectionTimeout"))
|
|
161
|
+
{
|
|
162
|
+
if (!config.Get("connectionTimeout").IsNumber())
|
|
163
|
+
{
|
|
164
|
+
Napi::TypeError::New(info.Env(), "connectionTimeout must be a number").ThrowAsJavaScriptException();
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
webSocketConfig.connectionTimeout =
|
|
168
|
+
std::chrono::milliseconds(config.Get("connectionTimeout").ToNumber().Int64Value());
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (config.Has("pingInterval"))
|
|
172
|
+
{
|
|
173
|
+
if (!config.Get("pingInterval").IsNumber())
|
|
174
|
+
{
|
|
175
|
+
Napi::TypeError::New(info.Env(), "pingInterval must be a number").ThrowAsJavaScriptException();
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
webSocketConfig.pingInterval = std::chrono::milliseconds(config.Get("pingInterval").ToNumber().Int64Value());
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (config.Has("maxOutstandingPings"))
|
|
182
|
+
{
|
|
183
|
+
if (!config.Get("maxOutstandingPings").IsNumber())
|
|
184
|
+
{
|
|
185
|
+
Napi::TypeError::New(info.Env(), "maxOutstandingPings must be a number").ThrowAsJavaScriptException();
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
webSocketConfig.maxOutstandingPings = config.Get("maxOutstandingPings").ToNumber().Int32Value();
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (config.Has("caCertificatePemFile"))
|
|
192
|
+
{
|
|
193
|
+
if (!config.Get("caCertificatePemFile").IsString())
|
|
194
|
+
{
|
|
195
|
+
Napi::TypeError::New(info.Env(), "caCertificatePemFile must be a string").ThrowAsJavaScriptException();
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
webSocketConfig.caCertificatePemFile = config.Get("caCertificatePemFile").ToString();
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (config.Has("certificatePemFile"))
|
|
202
|
+
{
|
|
203
|
+
if (!config.Get("certificatePemFile").IsString())
|
|
204
|
+
{
|
|
205
|
+
Napi::TypeError::New(info.Env(), "certificatePemFile must be a string").ThrowAsJavaScriptException();
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
webSocketConfig.certificatePemFile = config.Get("certificatePemFile").ToString();
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (config.Has("keyPemFile"))
|
|
212
|
+
{
|
|
213
|
+
if (!config.Get("keyPemFile").IsString())
|
|
214
|
+
{
|
|
215
|
+
Napi::TypeError::New(info.Env(), "keyPemFile must be a string").ThrowAsJavaScriptException();
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
webSocketConfig.keyPemFile = config.Get("keyPemFile").ToString();
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (config.Has("keyPemPass"))
|
|
222
|
+
{
|
|
223
|
+
if (!config.Get("keyPemPass").IsString())
|
|
224
|
+
{
|
|
225
|
+
Napi::TypeError::New(info.Env(), "keyPemPass must be a string").ThrowAsJavaScriptException();
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
webSocketConfig.keyPemPass = config.Get("keyPemPass").ToString();
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (config.Has("maxMessageSize"))
|
|
232
|
+
{
|
|
233
|
+
if (!config.Get("maxMessageSize").IsNumber())
|
|
234
|
+
{
|
|
235
|
+
Napi::TypeError::New(info.Env(), "maxMessageSize must be a number").ThrowAsJavaScriptException();
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
webSocketConfig.maxMessageSize = config.Get("maxMessageSize").ToNumber().Int32Value();
|
|
239
|
+
}
|
|
240
|
+
|
|
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
|
+
}
|
|
253
|
+
|
|
254
|
+
PLOG_DEBUG << "WebSocket created";
|
|
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);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
WebSocketWrapper::~WebSocketWrapper()
|
|
264
|
+
{
|
|
265
|
+
PLOG_DEBUG << "Destructor called";
|
|
266
|
+
doClose();
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
void WebSocketWrapper::doClose()
|
|
270
|
+
{
|
|
271
|
+
PLOG_DEBUG << "doClose() called";
|
|
272
|
+
if (mWebSocketPtr)
|
|
273
|
+
{
|
|
274
|
+
PLOG_DEBUG << "Closing...";
|
|
275
|
+
try
|
|
276
|
+
{
|
|
277
|
+
mWebSocketPtr->close();
|
|
278
|
+
mWebSocketPtr.reset();
|
|
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
|
+
}
|
|
286
|
+
|
|
287
|
+
mOnOpenCallback.reset();
|
|
288
|
+
mOnErrorCallback.reset();
|
|
289
|
+
mOnBufferedAmountLowCallback.reset();
|
|
290
|
+
mOnMessageCallback.reset();
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
void WebSocketWrapper::doForceClose()
|
|
294
|
+
{
|
|
295
|
+
PLOG_DEBUG << "doForceClose() called";
|
|
296
|
+
if (mWebSocketPtr)
|
|
297
|
+
{
|
|
298
|
+
PLOG_DEBUG << "Force closing...";
|
|
299
|
+
try
|
|
300
|
+
{
|
|
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;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
mOnOpenCallback.reset();
|
|
312
|
+
mOnErrorCallback.reset();
|
|
313
|
+
mOnBufferedAmountLowCallback.reset();
|
|
314
|
+
mOnMessageCallback.reset();
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
void WebSocketWrapper::doCleanup()
|
|
318
|
+
{
|
|
319
|
+
PLOG_DEBUG << "doCleanup() called";
|
|
320
|
+
mOnClosedCallback.reset();
|
|
321
|
+
instances.erase(this);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
void WebSocketWrapper::open(const Napi::CallbackInfo &info)
|
|
325
|
+
{
|
|
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
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
void WebSocketWrapper::close(const Napi::CallbackInfo &info)
|
|
353
|
+
{
|
|
354
|
+
PLOG_DEBUG << "close() called";
|
|
355
|
+
doClose();
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
void WebSocketWrapper::forceClose(const Napi::CallbackInfo &info)
|
|
359
|
+
{
|
|
360
|
+
PLOG_DEBUG << "forceClose() called";
|
|
361
|
+
doForceClose();
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
Napi::Value WebSocketWrapper::sendMessage(const Napi::CallbackInfo &info)
|
|
365
|
+
{
|
|
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
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
Napi::Value WebSocketWrapper::sendMessageBinary(const Napi::CallbackInfo &info)
|
|
396
|
+
{
|
|
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
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
Napi::Value WebSocketWrapper::isOpen(const Napi::CallbackInfo &info)
|
|
427
|
+
{
|
|
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
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
Napi::Value WebSocketWrapper::bufferedAmount(const Napi::CallbackInfo &info)
|
|
448
|
+
{
|
|
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
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
Napi::Value WebSocketWrapper::maxMessageSize(const Napi::CallbackInfo &info)
|
|
469
|
+
{
|
|
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
|
+
}
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
Napi::Value WebSocketWrapper::remoteAddress(const Napi::CallbackInfo &info)
|
|
490
|
+
{
|
|
491
|
+
PLOG_DEBUG << "remoteAddress() called";
|
|
492
|
+
Napi::Env env = info.Env();
|
|
493
|
+
|
|
494
|
+
if (!mWebSocketPtr)
|
|
495
|
+
{
|
|
496
|
+
return env.Undefined();
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
try
|
|
500
|
+
{
|
|
501
|
+
auto address = mWebSocketPtr->remoteAddress();
|
|
502
|
+
if (address.has_value())
|
|
503
|
+
{
|
|
504
|
+
return Napi::String::New(info.Env(), address.value());
|
|
505
|
+
}
|
|
506
|
+
else
|
|
507
|
+
{
|
|
508
|
+
return env.Undefined();
|
|
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
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
Napi::Value WebSocketWrapper::path(const Napi::CallbackInfo &info)
|
|
519
|
+
{
|
|
520
|
+
PLOG_DEBUG << "path() called";
|
|
521
|
+
Napi::Env env = info.Env();
|
|
522
|
+
|
|
523
|
+
if (!mWebSocketPtr)
|
|
524
|
+
{
|
|
525
|
+
return env.Undefined();
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
try
|
|
529
|
+
{
|
|
530
|
+
auto path = mWebSocketPtr->path();
|
|
531
|
+
if (path.has_value())
|
|
532
|
+
{
|
|
533
|
+
return Napi::String::New(info.Env(), path.value());
|
|
534
|
+
}
|
|
535
|
+
else
|
|
536
|
+
{
|
|
537
|
+
return env.Undefined();
|
|
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
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
void WebSocketWrapper::setBufferedAmountLowThreshold(const Napi::CallbackInfo &info)
|
|
548
|
+
{
|
|
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
|
+
}
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
void WebSocketWrapper::onOpen(const Napi::CallbackInfo &info)
|
|
578
|
+
{
|
|
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
|
+
}
|
|
614
|
+
|
|
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
|
+
});
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
void WebSocketWrapper::onClosed(const Napi::CallbackInfo &info)
|
|
624
|
+
{
|
|
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
|
+
});
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
void WebSocketWrapper::onError(const Napi::CallbackInfo &info)
|
|
664
|
+
{
|
|
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
|
+
});
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
void WebSocketWrapper::onBufferedAmountLow(const Napi::CallbackInfo &info)
|
|
706
|
+
{
|
|
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
|
+
});
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
void WebSocketWrapper::onMessage(const Napi::CallbackInfo &info)
|
|
748
|
+
{
|
|
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
|
+
});
|
|
796
|
+
}
|