@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,530 @@
|
|
|
1
|
+
#include "data-channel-wrapper.h"
|
|
2
|
+
#include "plog/Log.h"
|
|
3
|
+
|
|
4
|
+
Napi::FunctionReference DataChannelWrapper::constructor = Napi::FunctionReference();
|
|
5
|
+
std::unordered_set<DataChannelWrapper *> DataChannelWrapper::instances;
|
|
6
|
+
|
|
7
|
+
void DataChannelWrapper::CloseAll()
|
|
8
|
+
{
|
|
9
|
+
PLOG_DEBUG << "CloseAll() called";
|
|
10
|
+
auto copy(instances);
|
|
11
|
+
for (auto inst : copy)
|
|
12
|
+
inst->doClose();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
void DataChannelWrapper::CleanupAll()
|
|
16
|
+
{
|
|
17
|
+
PLOG_DEBUG << "CleanupAll() called";
|
|
18
|
+
auto copy(instances);
|
|
19
|
+
for (auto inst : copy)
|
|
20
|
+
inst->doCleanup();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
Napi::Object DataChannelWrapper::Init(Napi::Env env, Napi::Object exports)
|
|
24
|
+
{
|
|
25
|
+
Napi::HandleScope scope(env);
|
|
26
|
+
|
|
27
|
+
Napi::Function func = DefineClass(
|
|
28
|
+
env, "DataChannel",
|
|
29
|
+
{
|
|
30
|
+
InstanceMethod("close", &DataChannelWrapper::close),
|
|
31
|
+
InstanceMethod("getLabel", &DataChannelWrapper::getLabel),
|
|
32
|
+
InstanceMethod("getId", &DataChannelWrapper::getId),
|
|
33
|
+
InstanceMethod("getProtocol", &DataChannelWrapper::getProtocol),
|
|
34
|
+
InstanceMethod("sendMessage", &DataChannelWrapper::sendMessage),
|
|
35
|
+
InstanceMethod("sendMessageBinary", &DataChannelWrapper::sendMessageBinary),
|
|
36
|
+
InstanceMethod("isOpen", &DataChannelWrapper::isOpen),
|
|
37
|
+
InstanceMethod("bufferedAmount", &DataChannelWrapper::bufferedAmount),
|
|
38
|
+
InstanceMethod("maxMessageSize", &DataChannelWrapper::maxMessageSize),
|
|
39
|
+
InstanceMethod("setBufferedAmountLowThreshold", &DataChannelWrapper::setBufferedAmountLowThreshold),
|
|
40
|
+
InstanceMethod("onOpen", &DataChannelWrapper::onOpen),
|
|
41
|
+
InstanceMethod("onClosed", &DataChannelWrapper::onClosed),
|
|
42
|
+
InstanceMethod("onError", &DataChannelWrapper::onError),
|
|
43
|
+
InstanceMethod("onBufferedAmountLow", &DataChannelWrapper::onBufferedAmountLow),
|
|
44
|
+
InstanceMethod("onMessage", &DataChannelWrapper::onMessage),
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// If this is not the first call, we don't want to reassign the constructor (hot-reload problem)
|
|
48
|
+
if (constructor.IsEmpty())
|
|
49
|
+
{
|
|
50
|
+
constructor = Napi::Persistent(func);
|
|
51
|
+
constructor.SuppressDestruct();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
exports.Set("DataChannel", func);
|
|
55
|
+
return exports;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
DataChannelWrapper::DataChannelWrapper(const Napi::CallbackInfo &info) : Napi::ObjectWrap<DataChannelWrapper>(info)
|
|
59
|
+
{
|
|
60
|
+
PLOG_DEBUG << "Constructor called";
|
|
61
|
+
mDataChannelPtr = *(info[0].As<Napi::External<std::shared_ptr<rtc::DataChannel>>>().Data());
|
|
62
|
+
PLOG_DEBUG << "Data Channel created";
|
|
63
|
+
|
|
64
|
+
// Closed callback must be set to trigger cleanup
|
|
65
|
+
mOnClosedCallback =
|
|
66
|
+
std::make_unique<ThreadSafeCallback>(Napi::Function::New(info.Env(), [](const Napi::CallbackInfo &) {}));
|
|
67
|
+
|
|
68
|
+
instances.insert(this);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
DataChannelWrapper::~DataChannelWrapper()
|
|
72
|
+
{
|
|
73
|
+
PLOG_DEBUG << "Destructor called";
|
|
74
|
+
doClose();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
void DataChannelWrapper::doClose()
|
|
78
|
+
{
|
|
79
|
+
PLOG_DEBUG << "doClose() called";
|
|
80
|
+
if (mDataChannelPtr)
|
|
81
|
+
{
|
|
82
|
+
PLOG_DEBUG << "Closing...";
|
|
83
|
+
try
|
|
84
|
+
{
|
|
85
|
+
mDataChannelPtr->close();
|
|
86
|
+
mDataChannelPtr.reset();
|
|
87
|
+
}
|
|
88
|
+
catch (std::exception &ex)
|
|
89
|
+
{
|
|
90
|
+
std::cerr << std::string("libdatachannel error while closing data channel: ") + ex.what() << std::endl;
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
mOnOpenCallback.reset();
|
|
96
|
+
mOnErrorCallback.reset();
|
|
97
|
+
mOnBufferedAmountLowCallback.reset();
|
|
98
|
+
mOnMessageCallback.reset();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
void DataChannelWrapper::doCleanup()
|
|
102
|
+
{
|
|
103
|
+
PLOG_DEBUG << "doCleanup() called";
|
|
104
|
+
mOnClosedCallback.reset();
|
|
105
|
+
|
|
106
|
+
// For close there are 3 cases:
|
|
107
|
+
// 1. Close was called from JS
|
|
108
|
+
// 2. Close was called from RTC
|
|
109
|
+
// 3. Close was not called from JS or RTC (we are destroying the object)
|
|
110
|
+
// This could be coming from rtc (case 2)
|
|
111
|
+
mDataChannelPtr.reset();
|
|
112
|
+
mOnOpenCallback.reset();
|
|
113
|
+
mOnErrorCallback.reset();
|
|
114
|
+
mOnBufferedAmountLowCallback.reset();
|
|
115
|
+
mOnMessageCallback.reset();
|
|
116
|
+
instances.erase(this);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
void DataChannelWrapper::close(const Napi::CallbackInfo &info)
|
|
120
|
+
{
|
|
121
|
+
PLOG_DEBUG << "close() called";
|
|
122
|
+
doClose();
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
Napi::Value DataChannelWrapper::getLabel(const Napi::CallbackInfo &info)
|
|
126
|
+
{
|
|
127
|
+
PLOG_DEBUG << "getLabel() called";
|
|
128
|
+
if (!mDataChannelPtr)
|
|
129
|
+
{
|
|
130
|
+
Napi::Error::New(info.Env(), "getLabel() called on destroyed channel").ThrowAsJavaScriptException();
|
|
131
|
+
return info.Env().Null();
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return Napi::String::New(info.Env(), mDataChannelPtr->label());
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
Napi::Value DataChannelWrapper::getId(const Napi::CallbackInfo &info)
|
|
138
|
+
{
|
|
139
|
+
PLOG_DEBUG << "getId() called";
|
|
140
|
+
if (!mDataChannelPtr)
|
|
141
|
+
{
|
|
142
|
+
Napi::Error::New(info.Env(), "getId() called on destroyed channel").ThrowAsJavaScriptException();
|
|
143
|
+
return info.Env().Null();
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return Napi::Number::New(info.Env(), mDataChannelPtr->id().value_or(-1));
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
Napi::Value DataChannelWrapper::getProtocol(const Napi::CallbackInfo &info)
|
|
150
|
+
{
|
|
151
|
+
PLOG_DEBUG << "getProtocol() called";
|
|
152
|
+
if (!mDataChannelPtr)
|
|
153
|
+
{
|
|
154
|
+
Napi::Error::New(info.Env(), "getProtocol() called on destroyed channel").ThrowAsJavaScriptException();
|
|
155
|
+
return info.Env().Null();
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return Napi::String::New(info.Env(), mDataChannelPtr->protocol());
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
Napi::Value DataChannelWrapper::sendMessage(const Napi::CallbackInfo &info)
|
|
162
|
+
{
|
|
163
|
+
PLOG_DEBUG << "sendMessage() called";
|
|
164
|
+
if (!mDataChannelPtr)
|
|
165
|
+
{
|
|
166
|
+
Napi::Error::New(info.Env(), "sendMessage() called on destroyed channel").ThrowAsJavaScriptException();
|
|
167
|
+
return info.Env().Null();
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
Napi::Env env = info.Env();
|
|
171
|
+
int length = info.Length();
|
|
172
|
+
|
|
173
|
+
// Allow call with NULL
|
|
174
|
+
if (length < 1 || (!info[0].IsString() && !info[0].IsNull()))
|
|
175
|
+
{
|
|
176
|
+
Napi::TypeError::New(env, "String or Null expected").ThrowAsJavaScriptException();
|
|
177
|
+
return info.Env().Null();
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
try
|
|
181
|
+
{
|
|
182
|
+
return Napi::Boolean::New(info.Env(), mDataChannelPtr->send(info[0].As<Napi::String>().ToString()));
|
|
183
|
+
}
|
|
184
|
+
catch (std::exception &ex)
|
|
185
|
+
{
|
|
186
|
+
Napi::Error::New(env, std::string("libdatachannel error while sending data channel message: ") + ex.what())
|
|
187
|
+
.ThrowAsJavaScriptException();
|
|
188
|
+
return Napi::Boolean::New(info.Env(), false);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
Napi::Value DataChannelWrapper::sendMessageBinary(const Napi::CallbackInfo &info)
|
|
193
|
+
{
|
|
194
|
+
PLOG_DEBUG << "sendMessageBinary() called";
|
|
195
|
+
if (!mDataChannelPtr)
|
|
196
|
+
{
|
|
197
|
+
Napi::Error::New(info.Env(), "sendMessagBinary() called on destroyed channel").ThrowAsJavaScriptException();
|
|
198
|
+
return info.Env().Null();
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
Napi::Env env = info.Env();
|
|
202
|
+
int length = info.Length();
|
|
203
|
+
|
|
204
|
+
if (length < 1 || !info[0].IsBuffer())
|
|
205
|
+
{
|
|
206
|
+
Napi::TypeError::New(env, "Buffer expected").ThrowAsJavaScriptException();
|
|
207
|
+
return info.Env().Null();
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
try
|
|
211
|
+
{
|
|
212
|
+
Napi::Uint8Array buffer = info[0].As<Napi::Uint8Array>();
|
|
213
|
+
return Napi::Boolean::New(info.Env(), mDataChannelPtr->send((std::byte *)buffer.Data(), buffer.ByteLength()));
|
|
214
|
+
}
|
|
215
|
+
catch (std::exception &ex)
|
|
216
|
+
{
|
|
217
|
+
Napi::Error::New(env, std::string("libdatachannel error while sending data channel message: ") + ex.what())
|
|
218
|
+
.ThrowAsJavaScriptException();
|
|
219
|
+
return Napi::Boolean::New(info.Env(), false);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
Napi::Value DataChannelWrapper::isOpen(const Napi::CallbackInfo &info)
|
|
224
|
+
{
|
|
225
|
+
PLOG_DEBUG << "isOpen() called";
|
|
226
|
+
Napi::Env env = info.Env();
|
|
227
|
+
|
|
228
|
+
if (!mDataChannelPtr)
|
|
229
|
+
{
|
|
230
|
+
return Napi::Boolean::New(info.Env(), false);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
try
|
|
234
|
+
{
|
|
235
|
+
return Napi::Boolean::New(info.Env(), mDataChannelPtr->isOpen());
|
|
236
|
+
}
|
|
237
|
+
catch (std::exception &ex)
|
|
238
|
+
{
|
|
239
|
+
Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
|
|
240
|
+
return Napi::Boolean::New(info.Env(), false);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
Napi::Value DataChannelWrapper::bufferedAmount(const Napi::CallbackInfo &info)
|
|
245
|
+
{
|
|
246
|
+
PLOG_DEBUG << "bufferedAmount() called";
|
|
247
|
+
Napi::Env env = info.Env();
|
|
248
|
+
|
|
249
|
+
if (!mDataChannelPtr)
|
|
250
|
+
{
|
|
251
|
+
return Napi::Number::New(info.Env(), 0);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
try
|
|
255
|
+
{
|
|
256
|
+
return Napi::Number::New(info.Env(), mDataChannelPtr->bufferedAmount());
|
|
257
|
+
}
|
|
258
|
+
catch (std::exception &ex)
|
|
259
|
+
{
|
|
260
|
+
Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
|
|
261
|
+
return Napi::Number::New(info.Env(), 0);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
Napi::Value DataChannelWrapper::maxMessageSize(const Napi::CallbackInfo &info)
|
|
266
|
+
{
|
|
267
|
+
PLOG_DEBUG << "maxMessageSize() called";
|
|
268
|
+
Napi::Env env = info.Env();
|
|
269
|
+
|
|
270
|
+
if (!mDataChannelPtr)
|
|
271
|
+
{
|
|
272
|
+
return Napi::Number::New(info.Env(), 0);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
try
|
|
276
|
+
{
|
|
277
|
+
return Napi::Number::New(info.Env(), mDataChannelPtr->maxMessageSize());
|
|
278
|
+
}
|
|
279
|
+
catch (std::exception &ex)
|
|
280
|
+
{
|
|
281
|
+
Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
|
|
282
|
+
return Napi::Number::New(info.Env(), 0);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
void DataChannelWrapper::setBufferedAmountLowThreshold(const Napi::CallbackInfo &info)
|
|
287
|
+
{
|
|
288
|
+
PLOG_DEBUG << "setBufferedAmountLowThreshold() called";
|
|
289
|
+
if (!mDataChannelPtr)
|
|
290
|
+
{
|
|
291
|
+
Napi::Error::New(info.Env(), "setBufferedAmountLowThreshold() called on destroyed channel")
|
|
292
|
+
.ThrowAsJavaScriptException();
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
Napi::Env env = info.Env();
|
|
297
|
+
int length = info.Length();
|
|
298
|
+
|
|
299
|
+
if (length < 1 || !info[0].IsNumber())
|
|
300
|
+
{
|
|
301
|
+
Napi::TypeError::New(env, "Number expected").ThrowAsJavaScriptException();
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
try
|
|
306
|
+
{
|
|
307
|
+
mDataChannelPtr->setBufferedAmountLowThreshold(info[0].ToNumber().Uint32Value());
|
|
308
|
+
}
|
|
309
|
+
catch (std::exception &ex)
|
|
310
|
+
{
|
|
311
|
+
Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
void DataChannelWrapper::onOpen(const Napi::CallbackInfo &info)
|
|
317
|
+
{
|
|
318
|
+
PLOG_DEBUG << "onOpen() called";
|
|
319
|
+
if (!mDataChannelPtr)
|
|
320
|
+
{
|
|
321
|
+
Napi::Error::New(info.Env(), "onOpen() called on destroyed channel").ThrowAsJavaScriptException();
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
Napi::Env env = info.Env();
|
|
326
|
+
int length = info.Length();
|
|
327
|
+
|
|
328
|
+
if (length < 1 || !info[0].IsFunction())
|
|
329
|
+
{
|
|
330
|
+
Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// Callback
|
|
335
|
+
mOnOpenCallback = std::make_unique<ThreadSafeCallback>(info[0].As<Napi::Function>());
|
|
336
|
+
|
|
337
|
+
mDataChannelPtr->onOpen(
|
|
338
|
+
[&]()
|
|
339
|
+
{
|
|
340
|
+
PLOG_DEBUG << "onOpen cb received from rtc";
|
|
341
|
+
if (mOnOpenCallback)
|
|
342
|
+
mOnOpenCallback->call(
|
|
343
|
+
[this](Napi::Env env, std::vector<napi_value> &args)
|
|
344
|
+
{
|
|
345
|
+
PLOG_DEBUG << "mOnOpenCallback call(1)";
|
|
346
|
+
// Check the data channel is not closed
|
|
347
|
+
if (instances.find(this) == instances.end())
|
|
348
|
+
throw ThreadSafeCallback::CancelException();
|
|
349
|
+
|
|
350
|
+
// This will run in main thread and needs to construct the
|
|
351
|
+
// arguments for the call
|
|
352
|
+
args = {};
|
|
353
|
+
PLOG_DEBUG << "mOnOpenCallback call(2)";
|
|
354
|
+
});
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
void DataChannelWrapper::onClosed(const Napi::CallbackInfo &info)
|
|
359
|
+
{
|
|
360
|
+
PLOG_DEBUG << "onClosed() called";
|
|
361
|
+
if (!mDataChannelPtr)
|
|
362
|
+
{
|
|
363
|
+
Napi::Error::New(info.Env(), "onClosed() called on destroyed channel").ThrowAsJavaScriptException();
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
Napi::Env env = info.Env();
|
|
368
|
+
int length = info.Length();
|
|
369
|
+
|
|
370
|
+
if (length < 1 || !info[0].IsFunction())
|
|
371
|
+
{
|
|
372
|
+
Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// Callback
|
|
377
|
+
mOnClosedCallback = std::make_unique<ThreadSafeCallback>(info[0].As<Napi::Function>());
|
|
378
|
+
|
|
379
|
+
mDataChannelPtr->onClosed(
|
|
380
|
+
[&]()
|
|
381
|
+
{
|
|
382
|
+
PLOG_DEBUG << "onClosed cb received from rtc";
|
|
383
|
+
if (mOnClosedCallback)
|
|
384
|
+
mOnClosedCallback->call(
|
|
385
|
+
[this](Napi::Env env, std::vector<napi_value> &args)
|
|
386
|
+
{
|
|
387
|
+
PLOG_DEBUG << "mOnClosedCallback call";
|
|
388
|
+
// Do not check if the data channel has been closed here
|
|
389
|
+
|
|
390
|
+
// This will run in main thread and needs to construct the
|
|
391
|
+
// arguments for the call
|
|
392
|
+
args = {};
|
|
393
|
+
},
|
|
394
|
+
[this] { doCleanup(); });
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
void DataChannelWrapper::onError(const Napi::CallbackInfo &info)
|
|
399
|
+
{
|
|
400
|
+
PLOG_DEBUG << "onError() called";
|
|
401
|
+
if (!mDataChannelPtr)
|
|
402
|
+
{
|
|
403
|
+
Napi::Error::New(info.Env(), "onError() called on destroyed channel").ThrowAsJavaScriptException();
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
Napi::Env env = info.Env();
|
|
408
|
+
int length = info.Length();
|
|
409
|
+
|
|
410
|
+
if (length < 1 || !info[0].IsFunction())
|
|
411
|
+
{
|
|
412
|
+
Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// Callback
|
|
417
|
+
mOnErrorCallback = std::make_unique<ThreadSafeCallback>(info[0].As<Napi::Function>());
|
|
418
|
+
|
|
419
|
+
mDataChannelPtr->onError(
|
|
420
|
+
[&](std::string error)
|
|
421
|
+
{
|
|
422
|
+
PLOG_DEBUG << "onError cb received from rtc";
|
|
423
|
+
if (mOnErrorCallback)
|
|
424
|
+
mOnErrorCallback->call(
|
|
425
|
+
[this, error = std::move(error)](Napi::Env env, std::vector<napi_value> &args)
|
|
426
|
+
{
|
|
427
|
+
PLOG_DEBUG << "mOnErrorCallback call(1)";
|
|
428
|
+
// Check the data channel is not closed
|
|
429
|
+
if (instances.find(this) == instances.end())
|
|
430
|
+
throw ThreadSafeCallback::CancelException();
|
|
431
|
+
|
|
432
|
+
// This will run in main thread and needs to construct the
|
|
433
|
+
// arguments for the call
|
|
434
|
+
args = {Napi::String::New(env, error)};
|
|
435
|
+
PLOG_DEBUG << "mOnErrorCallback call(2)";
|
|
436
|
+
});
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
void DataChannelWrapper::onBufferedAmountLow(const Napi::CallbackInfo &info)
|
|
441
|
+
{
|
|
442
|
+
PLOG_DEBUG << "onBufferedAmountLow() called";
|
|
443
|
+
if (!mDataChannelPtr)
|
|
444
|
+
{
|
|
445
|
+
Napi::Error::New(info.Env(), "onBufferedAmountLow() called on destroyed channel").ThrowAsJavaScriptException();
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
Napi::Env env = info.Env();
|
|
450
|
+
int length = info.Length();
|
|
451
|
+
|
|
452
|
+
if (length < 1 || !info[0].IsFunction())
|
|
453
|
+
{
|
|
454
|
+
Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// Callback
|
|
459
|
+
mOnBufferedAmountLowCallback = std::make_unique<ThreadSafeCallback>(info[0].As<Napi::Function>());
|
|
460
|
+
|
|
461
|
+
mDataChannelPtr->onBufferedAmountLow(
|
|
462
|
+
[&]()
|
|
463
|
+
{
|
|
464
|
+
PLOG_DEBUG << "onBufferedAmountLow cb received from rtc";
|
|
465
|
+
if (mOnBufferedAmountLowCallback)
|
|
466
|
+
mOnBufferedAmountLowCallback->call(
|
|
467
|
+
[this](Napi::Env env, std::vector<napi_value> &args)
|
|
468
|
+
{
|
|
469
|
+
PLOG_DEBUG << "mOnBufferedAmountLowCallback call(1)";
|
|
470
|
+
// Check the data channel is not closed
|
|
471
|
+
if (instances.find(this) == instances.end())
|
|
472
|
+
throw ThreadSafeCallback::CancelException();
|
|
473
|
+
|
|
474
|
+
// This will run in main thread and needs to construct the
|
|
475
|
+
// arguments for the call
|
|
476
|
+
args = {};
|
|
477
|
+
PLOG_DEBUG << "mOnBufferedAmountLowCallback call(2)";
|
|
478
|
+
});
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
void DataChannelWrapper::onMessage(const Napi::CallbackInfo &info)
|
|
483
|
+
{
|
|
484
|
+
PLOG_DEBUG << "onMessage() called";
|
|
485
|
+
if (!mDataChannelPtr)
|
|
486
|
+
{
|
|
487
|
+
Napi::Error::New(info.Env(), "onMessage() called on destroyed channel").ThrowAsJavaScriptException();
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
Napi::Env env = info.Env();
|
|
492
|
+
int length = info.Length();
|
|
493
|
+
|
|
494
|
+
if (length < 1 || !info[0].IsFunction())
|
|
495
|
+
{
|
|
496
|
+
Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// Callback
|
|
501
|
+
mOnMessageCallback = std::make_unique<ThreadSafeCallback>(info[0].As<Napi::Function>());
|
|
502
|
+
|
|
503
|
+
mDataChannelPtr->onMessage(
|
|
504
|
+
[&](std::variant<rtc::binary, std::string> message)
|
|
505
|
+
{
|
|
506
|
+
PLOG_DEBUG << "onMessage cb received from rtc";
|
|
507
|
+
if (mOnMessageCallback)
|
|
508
|
+
mOnMessageCallback->call(
|
|
509
|
+
[this, message = std::move(message)](Napi::Env env, std::vector<napi_value> &args)
|
|
510
|
+
{
|
|
511
|
+
PLOG_DEBUG << "mOnMessageCallback call(1)";
|
|
512
|
+
// Check the data channel is not closed
|
|
513
|
+
if (instances.find(this) == instances.end())
|
|
514
|
+
throw ThreadSafeCallback::CancelException();
|
|
515
|
+
|
|
516
|
+
// This will run in main thread and needs to construct the
|
|
517
|
+
// arguments for the call
|
|
518
|
+
if (std::holds_alternative<std::string>(message))
|
|
519
|
+
{
|
|
520
|
+
args = {Napi::String::New(env, std::get<std::string>(message))};
|
|
521
|
+
}
|
|
522
|
+
else
|
|
523
|
+
{
|
|
524
|
+
auto bin = std::get<rtc::binary>(std::move(message));
|
|
525
|
+
args = {Napi::Buffer<std::byte>::Copy(env, bin.data(), bin.size())};
|
|
526
|
+
}
|
|
527
|
+
PLOG_DEBUG << "mOnMessageCallback call(2)";
|
|
528
|
+
});
|
|
529
|
+
});
|
|
530
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
#ifndef DATA_CHANNEL_WRAPPER_H
|
|
2
|
+
#define DATA_CHANNEL_WRAPPER_H
|
|
3
|
+
|
|
4
|
+
#include <string>
|
|
5
|
+
#include <memory>
|
|
6
|
+
#include <unordered_set>
|
|
7
|
+
|
|
8
|
+
#include <napi.h>
|
|
9
|
+
#include <rtc/rtc.hpp>
|
|
10
|
+
|
|
11
|
+
#include "thread-safe-callback.h"
|
|
12
|
+
|
|
13
|
+
class DataChannelWrapper : public Napi::ObjectWrap<DataChannelWrapper>
|
|
14
|
+
{
|
|
15
|
+
public:
|
|
16
|
+
static Napi::FunctionReference constructor;
|
|
17
|
+
static Napi::Object Init(Napi::Env env, Napi::Object exports);
|
|
18
|
+
DataChannelWrapper(const Napi::CallbackInfo &info);
|
|
19
|
+
~DataChannelWrapper();
|
|
20
|
+
|
|
21
|
+
// Functions
|
|
22
|
+
void close(const Napi::CallbackInfo &info);
|
|
23
|
+
Napi::Value getLabel(const Napi::CallbackInfo &info);
|
|
24
|
+
Napi::Value getId(const Napi::CallbackInfo &info);
|
|
25
|
+
Napi::Value getProtocol(const Napi::CallbackInfo &info);
|
|
26
|
+
Napi::Value sendMessage(const Napi::CallbackInfo &info);
|
|
27
|
+
Napi::Value sendMessageBinary(const Napi::CallbackInfo &info);
|
|
28
|
+
Napi::Value isOpen(const Napi::CallbackInfo &info);
|
|
29
|
+
Napi::Value bufferedAmount(const Napi::CallbackInfo &info);
|
|
30
|
+
Napi::Value maxMessageSize(const Napi::CallbackInfo &info);
|
|
31
|
+
void setBufferedAmountLowThreshold(const Napi::CallbackInfo &info);
|
|
32
|
+
|
|
33
|
+
// Callbacks
|
|
34
|
+
void onOpen(const Napi::CallbackInfo &info);
|
|
35
|
+
void onClosed(const Napi::CallbackInfo &info);
|
|
36
|
+
void onError(const Napi::CallbackInfo &info);
|
|
37
|
+
void onBufferedAmountLow(const Napi::CallbackInfo &info);
|
|
38
|
+
void onMessage(const Napi::CallbackInfo &info);
|
|
39
|
+
|
|
40
|
+
// Close all existing DataChannels
|
|
41
|
+
static void CloseAll();
|
|
42
|
+
|
|
43
|
+
// Reset all Callbacks for existing DataChannels
|
|
44
|
+
static void CleanupAll();
|
|
45
|
+
|
|
46
|
+
private:
|
|
47
|
+
static std::unordered_set<DataChannelWrapper *> instances;
|
|
48
|
+
|
|
49
|
+
void doClose();
|
|
50
|
+
void doCleanup();
|
|
51
|
+
|
|
52
|
+
std::string mLabel;
|
|
53
|
+
std::shared_ptr<rtc::DataChannel> mDataChannelPtr = nullptr;
|
|
54
|
+
|
|
55
|
+
// Callback Ptrs
|
|
56
|
+
std::unique_ptr<ThreadSafeCallback> mOnOpenCallback = nullptr;
|
|
57
|
+
std::unique_ptr<ThreadSafeCallback> mOnClosedCallback = nullptr;
|
|
58
|
+
std::unique_ptr<ThreadSafeCallback> mOnErrorCallback = nullptr;
|
|
59
|
+
std::unique_ptr<ThreadSafeCallback> mOnBufferedAmountLowCallback = nullptr;
|
|
60
|
+
std::unique_ptr<ThreadSafeCallback> mOnMessageCallback = nullptr;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
#endif // DATA_CHANNEL_WRAPPER_H
|