node-datachannel 0.27.0 → 0.29.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/.eslintrc.json +25 -25
- package/.prettierignore +7 -0
- package/.prettierrc +1 -0
- package/API.md +34 -4
- package/BULDING.md +12 -2
- package/CMakeLists.txt +10 -4
- package/README.md +22 -18
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/lib/datachannel-stream.cjs +13 -13
- package/dist/cjs/lib/datachannel-stream.cjs.map +1 -1
- package/dist/cjs/lib/index.cjs +4 -1
- package/dist/cjs/lib/index.cjs.map +1 -1
- package/dist/cjs/lib/websocket-server.cjs.map +1 -1
- package/dist/cjs/lib/websocket.cjs.map +1 -1
- package/dist/cjs/polyfill/Events.cjs +52 -3
- package/dist/cjs/polyfill/Events.cjs.map +1 -1
- package/dist/cjs/polyfill/Exception.cjs.map +1 -1
- package/dist/cjs/polyfill/RTCCertificate.cjs +5 -2
- package/dist/cjs/polyfill/RTCCertificate.cjs.map +1 -1
- package/dist/cjs/polyfill/RTCDataChannel.cjs +43 -22
- package/dist/cjs/polyfill/RTCDataChannel.cjs.map +1 -1
- package/dist/cjs/polyfill/RTCDtlsTransport.cjs +6 -5
- package/dist/cjs/polyfill/RTCDtlsTransport.cjs.map +1 -1
- package/dist/cjs/polyfill/RTCError.cjs +9 -2
- package/dist/cjs/polyfill/RTCError.cjs.map +1 -1
- package/dist/cjs/polyfill/RTCIceCandidate.cjs +13 -8
- package/dist/cjs/polyfill/RTCIceCandidate.cjs.map +1 -1
- package/dist/cjs/polyfill/RTCIceTransport.cjs +26 -16
- package/dist/cjs/polyfill/RTCIceTransport.cjs.map +1 -1
- package/dist/cjs/polyfill/RTCPeerConnection.cjs +80 -70
- package/dist/cjs/polyfill/RTCPeerConnection.cjs.map +1 -1
- package/dist/cjs/polyfill/RTCSctpTransport.cjs +9 -11
- package/dist/cjs/polyfill/RTCSctpTransport.cjs.map +1 -1
- package/dist/cjs/polyfill/RTCSessionDescription.cjs +10 -2
- package/dist/cjs/polyfill/RTCSessionDescription.cjs.map +1 -1
- package/dist/cjs/polyfill/index.cjs.map +1 -1
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/lib/datachannel-stream.mjs.map +1 -1
- package/dist/esm/lib/index.mjs +4 -2
- package/dist/esm/lib/index.mjs.map +1 -1
- package/dist/esm/lib/websocket-server.mjs.map +1 -1
- package/dist/esm/lib/websocket.mjs.map +1 -1
- package/dist/esm/polyfill/Events.mjs +52 -4
- package/dist/esm/polyfill/Events.mjs.map +1 -1
- package/dist/esm/polyfill/Exception.mjs.map +1 -1
- package/dist/esm/polyfill/RTCCertificate.mjs +5 -2
- package/dist/esm/polyfill/RTCCertificate.mjs.map +1 -1
- package/dist/esm/polyfill/RTCDataChannel.mjs +43 -22
- package/dist/esm/polyfill/RTCDataChannel.mjs.map +1 -1
- package/dist/esm/polyfill/RTCDtlsTransport.mjs +6 -5
- package/dist/esm/polyfill/RTCDtlsTransport.mjs.map +1 -1
- package/dist/esm/polyfill/RTCError.mjs +9 -2
- package/dist/esm/polyfill/RTCError.mjs.map +1 -1
- package/dist/esm/polyfill/RTCIceCandidate.mjs +13 -8
- package/dist/esm/polyfill/RTCIceCandidate.mjs.map +1 -1
- package/dist/esm/polyfill/RTCIceTransport.mjs +26 -17
- package/dist/esm/polyfill/RTCIceTransport.mjs.map +1 -1
- package/dist/esm/polyfill/RTCPeerConnection.mjs +80 -70
- package/dist/esm/polyfill/RTCPeerConnection.mjs.map +1 -1
- package/dist/esm/polyfill/RTCSctpTransport.mjs +9 -11
- package/dist/esm/polyfill/RTCSctpTransport.mjs.map +1 -1
- package/dist/esm/polyfill/RTCSessionDescription.mjs +10 -2
- package/dist/esm/polyfill/RTCSessionDescription.mjs.map +1 -1
- package/dist/esm/polyfill/index.mjs.map +1 -1
- package/dist/types/lib/index.d.ts +14 -3
- package/dist/types/lib/types.d.ts +30 -7
- package/dist/types/polyfill/Events.d.ts +4 -1
- package/dist/types/polyfill/RTCCertificate.d.ts +1 -0
- package/dist/types/polyfill/RTCDataChannel.d.ts +6 -6
- package/dist/types/polyfill/RTCDtlsTransport.d.ts +5 -4
- package/dist/types/polyfill/RTCError.d.ts +1 -0
- package/dist/types/polyfill/RTCIceCandidate.d.ts +1 -1
- package/dist/types/polyfill/RTCIceTransport.d.ts +17 -8
- package/dist/types/polyfill/RTCPeerConnection.d.ts +22 -11
- package/dist/types/polyfill/RTCSctpTransport.d.ts +4 -3
- package/dist/types/polyfill/RTCSessionDescription.d.ts +1 -0
- package/jest.config.ts +8 -8
- package/package.json +6 -3
- package/rollup.config.mjs +1 -1
- package/src/cpp/data-channel-wrapper.cpp +11 -0
- package/src/cpp/ice-udp-mux-listener-wrapper.cpp +150 -0
- package/src/cpp/ice-udp-mux-listener-wrapper.h +43 -0
- package/src/cpp/main.cpp +2 -0
- package/src/cpp/peer-connection-wrapper.cpp +68 -2
- package/src/cpp/peer-connection-wrapper.h +1 -0
- package/src/index.ts +0 -1
- package/src/lib/datachannel-stream.ts +83 -84
- package/src/lib/index.ts +175 -139
- package/src/lib/types.ts +122 -71
- package/src/lib/websocket-server.ts +25 -25
- package/src/lib/websocket.ts +19 -19
- package/src/polyfill/Events.ts +71 -18
- package/src/polyfill/Exception.ts +24 -24
- package/src/polyfill/README.md +8 -8
- package/src/polyfill/RTCCertificate.ts +16 -12
- package/src/polyfill/RTCDataChannel.ts +216 -191
- package/src/polyfill/RTCDtlsTransport.ts +39 -39
- package/src/polyfill/RTCError.ts +63 -56
- package/src/polyfill/RTCIceCandidate.ts +120 -116
- package/src/polyfill/RTCIceTransport.ts +72 -64
- package/src/polyfill/RTCPeerConnection.ts +436 -420
- package/src/polyfill/RTCSctpTransport.ts +44 -47
- package/src/polyfill/RTCSessionDescription.ts +26 -17
- package/src/polyfill/index.ts +22 -22
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
#include "ice-udp-mux-listener-wrapper.h"
|
|
2
|
+
|
|
3
|
+
#include "plog/Log.h"
|
|
4
|
+
|
|
5
|
+
#include <cctype>
|
|
6
|
+
#include <sstream>
|
|
7
|
+
|
|
8
|
+
Napi::FunctionReference IceUdpMuxListenerWrapper::constructor = Napi::FunctionReference();
|
|
9
|
+
std::unordered_set<IceUdpMuxListenerWrapper *> IceUdpMuxListenerWrapper::instances;
|
|
10
|
+
|
|
11
|
+
void IceUdpMuxListenerWrapper::StopAll()
|
|
12
|
+
{
|
|
13
|
+
PLOG_DEBUG << "IceUdpMuxListenerWrapper StopAll() called";
|
|
14
|
+
auto copy(instances);
|
|
15
|
+
for (auto inst : copy)
|
|
16
|
+
inst->doCleanup();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
Napi::Object IceUdpMuxListenerWrapper::Init(Napi::Env env, Napi::Object exports)
|
|
20
|
+
{
|
|
21
|
+
Napi::HandleScope scope(env);
|
|
22
|
+
|
|
23
|
+
Napi::Function func = DefineClass(
|
|
24
|
+
env,
|
|
25
|
+
"IceUdpMuxListener",
|
|
26
|
+
{
|
|
27
|
+
InstanceMethod("stop", &IceUdpMuxListenerWrapper::stop),
|
|
28
|
+
InstanceMethod("onUnhandledStunRequest", &IceUdpMuxListenerWrapper::onUnhandledStunRequest),
|
|
29
|
+
InstanceMethod("port", &IceUdpMuxListenerWrapper::port),
|
|
30
|
+
InstanceMethod("address", &IceUdpMuxListenerWrapper::address)
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// If this is not the first call, we don't want to reassign the constructor (hot-reload problem)
|
|
34
|
+
if(constructor.IsEmpty())
|
|
35
|
+
{
|
|
36
|
+
constructor = Napi::Persistent(func);
|
|
37
|
+
constructor.SuppressDestruct();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
exports.Set("IceUdpMuxListener", func);
|
|
41
|
+
return exports;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
IceUdpMuxListenerWrapper::IceUdpMuxListenerWrapper(const Napi::CallbackInfo &info) : Napi::ObjectWrap<IceUdpMuxListenerWrapper>(info)
|
|
45
|
+
{
|
|
46
|
+
PLOG_DEBUG << "IceUdpMuxListenerWrapper Constructor called";
|
|
47
|
+
Napi::Env env = info.Env();
|
|
48
|
+
int length = info.Length();
|
|
49
|
+
|
|
50
|
+
// We expect (Number, String?) as param
|
|
51
|
+
if (length > 0 && info[0].IsNumber()) {
|
|
52
|
+
// Port
|
|
53
|
+
mPort = info[0].As<Napi::Number>().ToNumber().Uint32Value();
|
|
54
|
+
} else {
|
|
55
|
+
Napi::TypeError::New(env, "Port (Number) and optional Address (String) expected").ThrowAsJavaScriptException();
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (length > 1 && info[1].IsString()) {
|
|
60
|
+
// Address
|
|
61
|
+
mAddress = info[1].As<Napi::String>().ToString();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
iceUdpMuxListenerPtr = std::make_unique<rtc::IceUdpMuxListener>(mPort, mAddress);
|
|
65
|
+
instances.insert(this);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
IceUdpMuxListenerWrapper::~IceUdpMuxListenerWrapper()
|
|
69
|
+
{
|
|
70
|
+
PLOG_DEBUG << "IceUdpMuxListenerWrapper Destructor called";
|
|
71
|
+
doCleanup();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
void IceUdpMuxListenerWrapper::doCleanup()
|
|
75
|
+
{
|
|
76
|
+
PLOG_DEBUG << "IceUdpMuxListenerWrapper::doCleanup() called";
|
|
77
|
+
|
|
78
|
+
if (iceUdpMuxListenerPtr)
|
|
79
|
+
{
|
|
80
|
+
iceUdpMuxListenerPtr->stop();
|
|
81
|
+
iceUdpMuxListenerPtr.reset();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
mOnUnhandledStunRequestCallback.reset();
|
|
85
|
+
instances.erase(this);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
Napi::Value IceUdpMuxListenerWrapper::port(const Napi::CallbackInfo &info)
|
|
89
|
+
{
|
|
90
|
+
Napi::Env env = info.Env();
|
|
91
|
+
|
|
92
|
+
return Napi::Number::New(env, mPort);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
Napi::Value IceUdpMuxListenerWrapper::address(const Napi::CallbackInfo &info)
|
|
96
|
+
{
|
|
97
|
+
Napi::Env env = info.Env();
|
|
98
|
+
|
|
99
|
+
if (!mAddress.has_value()) {
|
|
100
|
+
return env.Undefined();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return Napi::String::New(env, mAddress.value());
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
void IceUdpMuxListenerWrapper::stop(const Napi::CallbackInfo &info)
|
|
107
|
+
{
|
|
108
|
+
PLOG_DEBUG << "IceUdpMuxListenerWrapper::stop() called";
|
|
109
|
+
doCleanup();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
void IceUdpMuxListenerWrapper::onUnhandledStunRequest(const Napi::CallbackInfo &info)
|
|
113
|
+
{
|
|
114
|
+
PLOG_DEBUG << "IceUdpMuxListenerWrapper::onUnhandledStunRequest() called";
|
|
115
|
+
Napi::Env env = info.Env();
|
|
116
|
+
int length = info.Length();
|
|
117
|
+
|
|
118
|
+
if (!iceUdpMuxListenerPtr)
|
|
119
|
+
{
|
|
120
|
+
Napi::Error::New(env, "IceUdpMuxListenerWrapper::onUnhandledStunRequest() called on destroyed IceUdpMuxListener").ThrowAsJavaScriptException();
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (length < 1 || !info[0].IsFunction())
|
|
125
|
+
{
|
|
126
|
+
Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Callback
|
|
131
|
+
mOnUnhandledStunRequestCallback = std::make_unique<ThreadSafeCallback>(info[0].As<Napi::Function>());
|
|
132
|
+
|
|
133
|
+
iceUdpMuxListenerPtr->OnUnhandledStunRequest([&](rtc::IceUdpMuxRequest request)
|
|
134
|
+
{
|
|
135
|
+
PLOG_DEBUG << "IceUdpMuxListenerWrapper::onUnhandledStunRequest() IceUdpMuxCallback call(1)";
|
|
136
|
+
|
|
137
|
+
if (mOnUnhandledStunRequestCallback) {
|
|
138
|
+
mOnUnhandledStunRequestCallback->call([request = std::move(request)](Napi::Env env, std::vector<napi_value> &args) {
|
|
139
|
+
Napi::Object reqObj = Napi::Object::New(env);
|
|
140
|
+
reqObj.Set("ufrag", request.remoteUfrag.c_str());
|
|
141
|
+
reqObj.Set("host", request.remoteAddress.c_str());
|
|
142
|
+
reqObj.Set("port", request.remotePort);
|
|
143
|
+
|
|
144
|
+
args = {reqObj};
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
PLOG_DEBUG << "IceUdpMuxListenerWrapper::onUnhandledStunRequest() IceUdpMuxCallback call(2)";
|
|
149
|
+
});
|
|
150
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#ifndef ICE_UDP_MUX_LISTENER_WRAPPER_H
|
|
2
|
+
#define ICE_UDP_MUX_LISTENER_WRAPPER_H
|
|
3
|
+
|
|
4
|
+
#include <napi.h>
|
|
5
|
+
#include <rtc/rtc.hpp>
|
|
6
|
+
#include <unordered_set>
|
|
7
|
+
|
|
8
|
+
#include "thread-safe-callback.h"
|
|
9
|
+
|
|
10
|
+
class IceUdpMuxListenerWrapper : public Napi::ObjectWrap<IceUdpMuxListenerWrapper>
|
|
11
|
+
{
|
|
12
|
+
public:
|
|
13
|
+
static Napi::Object Init(Napi::Env env, Napi::Object exports);
|
|
14
|
+
IceUdpMuxListenerWrapper(const Napi::CallbackInfo &info);
|
|
15
|
+
~IceUdpMuxListenerWrapper();
|
|
16
|
+
|
|
17
|
+
// Functions
|
|
18
|
+
void stop(const Napi::CallbackInfo &info);
|
|
19
|
+
void onUnhandledStunRequest(const Napi::CallbackInfo &info);
|
|
20
|
+
|
|
21
|
+
// Stop listening on all ports
|
|
22
|
+
static void StopAll();
|
|
23
|
+
|
|
24
|
+
// Properties
|
|
25
|
+
Napi::Value port(const Napi::CallbackInfo &info);
|
|
26
|
+
Napi::Value address(const Napi::CallbackInfo &info);
|
|
27
|
+
Napi::Value unhandledStunRequestCallback(const Napi::CallbackInfo &info);
|
|
28
|
+
|
|
29
|
+
// Callback Ptrs
|
|
30
|
+
std::unique_ptr<ThreadSafeCallback> mOnUnhandledStunRequestCallback = nullptr;
|
|
31
|
+
|
|
32
|
+
private:
|
|
33
|
+
static Napi::FunctionReference constructor;
|
|
34
|
+
static std::unordered_set<IceUdpMuxListenerWrapper *> instances;
|
|
35
|
+
|
|
36
|
+
void doCleanup();
|
|
37
|
+
|
|
38
|
+
std::optional<std::string> mAddress;
|
|
39
|
+
uint16_t mPort;
|
|
40
|
+
std::unique_ptr<rtc::IceUdpMuxListener> iceUdpMuxListenerPtr = nullptr;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
#endif // ICE_UDP_MUX_LISTENER_WRAPPER_H
|
package/src/cpp/main.cpp
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
#include "rtc-wrapper.h"
|
|
3
3
|
#include "peer-connection-wrapper.h"
|
|
4
4
|
#include "data-channel-wrapper.h"
|
|
5
|
+
#include "ice-udp-mux-listener-wrapper.h"
|
|
5
6
|
|
|
6
7
|
#if RTC_ENABLE_MEDIA == 1
|
|
7
8
|
#include "media-rtcpreceivingsession-wrapper.h"
|
|
@@ -27,6 +28,7 @@ Napi::Object InitAll(Napi::Env env, Napi::Object exports)
|
|
|
27
28
|
#endif
|
|
28
29
|
|
|
29
30
|
DataChannelWrapper::Init(env, exports);
|
|
31
|
+
IceUdpMuxListenerWrapper::Init(env, exports);
|
|
30
32
|
PeerConnectionWrapper::Init(env, exports);
|
|
31
33
|
|
|
32
34
|
#if RTC_ENABLE_WEBSOCKET == 1
|
|
@@ -44,6 +44,7 @@ Napi::Object PeerConnectionWrapper::Init(Napi::Env env, Napi::Object exports)
|
|
|
44
44
|
InstanceMethod("setRemoteDescription", &PeerConnectionWrapper::setRemoteDescription),
|
|
45
45
|
InstanceMethod("localDescription", &PeerConnectionWrapper::localDescription),
|
|
46
46
|
InstanceMethod("remoteDescription", &PeerConnectionWrapper::remoteDescription),
|
|
47
|
+
InstanceMethod("remoteFingerprint", &PeerConnectionWrapper::remoteFingerprint),
|
|
47
48
|
InstanceMethod("addRemoteCandidate", &PeerConnectionWrapper::addRemoteCandidate),
|
|
48
49
|
InstanceMethod("createDataChannel", &PeerConnectionWrapper::createDataChannel),
|
|
49
50
|
|
|
@@ -220,6 +221,10 @@ PeerConnectionWrapper::PeerConnectionWrapper(const Napi::CallbackInfo &info) : N
|
|
|
220
221
|
if (config.Get("disableAutoNegotiation").IsBoolean())
|
|
221
222
|
rtcConfig.disableAutoNegotiation = config.Get("disableAutoNegotiation").As<Napi::Boolean>();
|
|
222
223
|
|
|
224
|
+
// disableAutoGathering option
|
|
225
|
+
if (config.Get("disableAutoGathering").IsBoolean())
|
|
226
|
+
rtcConfig.disableAutoGathering = config.Get("disableAutoGathering").As<Napi::Boolean>();
|
|
227
|
+
|
|
223
228
|
// forceMediaTransport option
|
|
224
229
|
if (config.Get("forceMediaTransport").IsBoolean())
|
|
225
230
|
rtcConfig.forceMediaTransport = config.Get("forceMediaTransport").As<Napi::Boolean>();
|
|
@@ -257,6 +262,17 @@ PeerConnectionWrapper::PeerConnectionWrapper(const Napi::CallbackInfo &info) : N
|
|
|
257
262
|
rtcConfig.disableFingerprintVerification = config.Get("disableFingerprintVerification").As<Napi::Boolean>();
|
|
258
263
|
}
|
|
259
264
|
|
|
265
|
+
// Specify certificate to use if set
|
|
266
|
+
if (config.Get("certificatePemFile").IsString()) {
|
|
267
|
+
rtcConfig.certificatePemFile = config.Get("certificatePemFile").As<Napi::String>().ToString();
|
|
268
|
+
}
|
|
269
|
+
if (config.Get("keyPemFile").IsString()) {
|
|
270
|
+
rtcConfig.keyPemFile = config.Get("keyPemFile").As<Napi::String>().ToString();
|
|
271
|
+
}
|
|
272
|
+
if (config.Get("keyPemPass").IsString()) {
|
|
273
|
+
rtcConfig.keyPemPass = config.Get("keyPemPass").As<Napi::String>().ToString();
|
|
274
|
+
}
|
|
275
|
+
|
|
260
276
|
// Create peer-connection
|
|
261
277
|
try
|
|
262
278
|
{
|
|
@@ -337,6 +353,7 @@ void PeerConnectionWrapper::setLocalDescription(const Napi::CallbackInfo &info)
|
|
|
337
353
|
}
|
|
338
354
|
|
|
339
355
|
rtc::Description::Type type = rtc::Description::Type::Unspec;
|
|
356
|
+
rtc::LocalDescriptionInit init;
|
|
340
357
|
|
|
341
358
|
// optional
|
|
342
359
|
if (length > 0)
|
|
@@ -362,7 +379,29 @@ void PeerConnectionWrapper::setLocalDescription(const Napi::CallbackInfo &info)
|
|
|
362
379
|
type = rtc::Description::Type::Rollback;
|
|
363
380
|
}
|
|
364
381
|
|
|
365
|
-
|
|
382
|
+
// optional
|
|
383
|
+
if (length > 1)
|
|
384
|
+
{
|
|
385
|
+
PLOG_DEBUG << "setLocalDescription() called with LocalDescriptionInit";
|
|
386
|
+
|
|
387
|
+
if (info[1].IsObject())
|
|
388
|
+
{
|
|
389
|
+
PLOG_DEBUG << "setLocalDescription() called with LocalDescriptionInit as object";
|
|
390
|
+
Napi::Object obj = info[1].As<Napi::Object>();
|
|
391
|
+
|
|
392
|
+
if (obj.Get("iceUfrag").IsString()) {
|
|
393
|
+
PLOG_DEBUG << "setLocalDescription() has ufrag";
|
|
394
|
+
init.iceUfrag = obj.Get("iceUfrag").As<Napi::String>();
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
if (obj.Get("icePwd").IsString()) {
|
|
398
|
+
PLOG_DEBUG << "setLocalDescription() has password";
|
|
399
|
+
init.icePwd = obj.Get("icePwd").As<Napi::String>();
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
mRtcPeerConnPtr->setLocalDescription(type, init);
|
|
366
405
|
}
|
|
367
406
|
|
|
368
407
|
void PeerConnectionWrapper::setRemoteDescription(const Napi::CallbackInfo &info)
|
|
@@ -1008,7 +1047,34 @@ Napi::Value PeerConnectionWrapper::maxMessageSize(const Napi::CallbackInfo &info
|
|
|
1008
1047
|
|
|
1009
1048
|
try
|
|
1010
1049
|
{
|
|
1011
|
-
return Napi::
|
|
1050
|
+
return Napi::Array::New(env, mRtcPeerConnPtr->remoteMaxMessageSize());
|
|
1051
|
+
}
|
|
1052
|
+
catch (std::exception &ex)
|
|
1053
|
+
{
|
|
1054
|
+
Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
|
|
1055
|
+
return Napi::Number::New(info.Env(), 0);
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
Napi::Value PeerConnectionWrapper::remoteFingerprint(const Napi::CallbackInfo &info)
|
|
1060
|
+
{
|
|
1061
|
+
PLOG_DEBUG << "remoteFingerprints() called";
|
|
1062
|
+
Napi::Env env = info.Env();
|
|
1063
|
+
|
|
1064
|
+
if (!mRtcPeerConnPtr)
|
|
1065
|
+
{
|
|
1066
|
+
return Napi::Number::New(info.Env(), 0);
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
try
|
|
1070
|
+
{
|
|
1071
|
+
auto fingerprint = mRtcPeerConnPtr->remoteFingerprint();
|
|
1072
|
+
|
|
1073
|
+
Napi::Object fingerprintObject = Napi::Object::New(env);
|
|
1074
|
+
fingerprintObject.Set("value", fingerprint.value);
|
|
1075
|
+
fingerprintObject.Set("algorithm", rtc::CertificateFingerprint::AlgorithmIdentifier(fingerprint.algorithm));
|
|
1076
|
+
|
|
1077
|
+
return fingerprintObject;
|
|
1012
1078
|
}
|
|
1013
1079
|
catch (std::exception &ex)
|
|
1014
1080
|
{
|
|
@@ -38,6 +38,7 @@ public:
|
|
|
38
38
|
Napi::Value iceState(const Napi::CallbackInfo &info);
|
|
39
39
|
Napi::Value signalingState(const Napi::CallbackInfo &info);
|
|
40
40
|
Napi::Value gatheringState(const Napi::CallbackInfo &info);
|
|
41
|
+
Napi::Value remoteFingerprint(const Napi::CallbackInfo &info);
|
|
41
42
|
|
|
42
43
|
// Callbacks
|
|
43
44
|
void onLocalDescription(const Napi::CallbackInfo &info);
|
package/src/index.ts
CHANGED
|
@@ -10,92 +10,91 @@ import * as stream from 'stream';
|
|
|
10
10
|
* the protocol level, and is preserved here throughout.
|
|
11
11
|
*/
|
|
12
12
|
export default class DataChannelStream extends stream.Duplex {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
rawChannel.onOpen(() => this.uncork());
|
|
48
|
-
}
|
|
13
|
+
private _rawChannel: any;
|
|
14
|
+
private _readActive: boolean;
|
|
15
|
+
|
|
16
|
+
constructor(rawChannel: any, streamOptions?: Omit<stream.DuplexOptions, 'objectMode'>) {
|
|
17
|
+
super({
|
|
18
|
+
allowHalfOpen: false, // Default to autoclose on end().
|
|
19
|
+
...streamOptions,
|
|
20
|
+
objectMode: true, // Preserve the string/buffer distinction (WebRTC treats them differently)
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
this._rawChannel = rawChannel;
|
|
24
|
+
this._readActive = true;
|
|
25
|
+
|
|
26
|
+
rawChannel.onMessage((msg: any) => {
|
|
27
|
+
if (!this._readActive) return; // If the buffer is full, drop messages.
|
|
28
|
+
|
|
29
|
+
// If the push is rejected, we pause reading until the next call to _read().
|
|
30
|
+
this._readActive = this.push(msg);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// When the DataChannel closes, the readable & writable ends close
|
|
34
|
+
rawChannel.onClosed(() => {
|
|
35
|
+
this.push(null);
|
|
36
|
+
this.destroy();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
rawChannel.onError((errMsg: string) => {
|
|
40
|
+
this.destroy(new Error(`DataChannel error: ${errMsg}`));
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Buffer all writes until the DataChannel opens
|
|
44
|
+
if (!rawChannel.isOpen()) {
|
|
45
|
+
this.cork();
|
|
46
|
+
rawChannel.onOpen(() => this.uncork());
|
|
49
47
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
if (sentOk) {
|
|
73
|
-
callback(null);
|
|
74
|
-
} else {
|
|
75
|
-
callback(new Error('Failed to write to DataChannel'));
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
_final(callback): void {
|
|
80
|
-
if (!this.allowHalfOpen) this.destroy();
|
|
81
|
-
callback(null);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
_destroy(maybeErr, callback): void {
|
|
85
|
-
// When the stream is destroyed, we close the DataChannel.
|
|
86
|
-
this._rawChannel.close();
|
|
87
|
-
callback(maybeErr);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
get label(): string {
|
|
91
|
-
return this._rawChannel.getLabel();
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
get id(): number {
|
|
95
|
-
return this._rawChannel.getId();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
_read(): void {
|
|
51
|
+
// Stop dropping messages, if the buffer filling up meant we were doing so before.
|
|
52
|
+
this._readActive = true;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
_write(chunk, _encoding, callback): void {
|
|
56
|
+
let sentOk;
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
if (Buffer.isBuffer(chunk)) {
|
|
60
|
+
sentOk = this._rawChannel.sendMessageBinary(chunk);
|
|
61
|
+
} else if (typeof chunk === 'string') {
|
|
62
|
+
sentOk = this._rawChannel.sendMessage(chunk);
|
|
63
|
+
} else {
|
|
64
|
+
const typeName = chunk.constructor.name || typeof chunk;
|
|
65
|
+
throw new Error(`Cannot write ${typeName} to DataChannel stream`);
|
|
66
|
+
}
|
|
67
|
+
} catch (err) {
|
|
68
|
+
return callback(err);
|
|
96
69
|
}
|
|
97
70
|
|
|
98
|
-
|
|
99
|
-
|
|
71
|
+
if (sentOk) {
|
|
72
|
+
callback(null);
|
|
73
|
+
} else {
|
|
74
|
+
callback(new Error('Failed to write to DataChannel'));
|
|
100
75
|
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
_final(callback): void {
|
|
79
|
+
if (!this.allowHalfOpen) this.destroy();
|
|
80
|
+
callback(null);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
_destroy(maybeErr, callback): void {
|
|
84
|
+
// When the stream is destroyed, we close the DataChannel.
|
|
85
|
+
this._rawChannel.close();
|
|
86
|
+
callback(maybeErr);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
get label(): string {
|
|
90
|
+
return this._rawChannel.getLabel();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
get id(): number {
|
|
94
|
+
return this._rawChannel.getId();
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
get protocol(): string {
|
|
98
|
+
return this._rawChannel.getProtocol();
|
|
99
|
+
}
|
|
101
100
|
}
|