@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.
Files changed (171) hide show
  1. package/.clang-format +17 -0
  2. package/.editorconfig +12 -0
  3. package/.eslintignore +8 -0
  4. package/.eslintrc.json +27 -0
  5. package/.gitmodules +3 -0
  6. package/.prettierignore +7 -0
  7. package/.prettierrc +13 -0
  8. package/API.md +247 -0
  9. package/BULDING.md +33 -0
  10. package/CMakeLists.txt +134 -0
  11. package/LICENSE +373 -0
  12. package/README.md +130 -0
  13. package/dist/cjs/index.cjs +11 -0
  14. package/dist/cjs/index.cjs.map +1 -0
  15. package/dist/cjs/lib/datachannel-stream.cjs +101 -0
  16. package/dist/cjs/lib/datachannel-stream.cjs.map +1 -0
  17. package/dist/cjs/lib/index.cjs +88 -0
  18. package/dist/cjs/lib/index.cjs.map +1 -0
  19. package/dist/cjs/lib/node-datachannel.cjs +8 -0
  20. package/dist/cjs/lib/node-datachannel.cjs.map +1 -0
  21. package/dist/cjs/lib/websocket-server.cjs +45 -0
  22. package/dist/cjs/lib/websocket-server.cjs.map +1 -0
  23. package/dist/cjs/lib/websocket.cjs +8 -0
  24. package/dist/cjs/lib/websocket.cjs.map +1 -0
  25. package/dist/cjs/polyfill/Events.cjs +86 -0
  26. package/dist/cjs/polyfill/Events.cjs.map +1 -0
  27. package/dist/cjs/polyfill/Exception.cjs +34 -0
  28. package/dist/cjs/polyfill/Exception.cjs.map +1 -0
  29. package/dist/cjs/polyfill/RTCCertificate.cjs +34 -0
  30. package/dist/cjs/polyfill/RTCCertificate.cjs.map +1 -0
  31. package/dist/cjs/polyfill/RTCDataChannel.cjs +214 -0
  32. package/dist/cjs/polyfill/RTCDataChannel.cjs.map +1 -0
  33. package/dist/cjs/polyfill/RTCDtlsTransport.cjs +53 -0
  34. package/dist/cjs/polyfill/RTCDtlsTransport.cjs.map +1 -0
  35. package/dist/cjs/polyfill/RTCError.cjs +83 -0
  36. package/dist/cjs/polyfill/RTCError.cjs.map +1 -0
  37. package/dist/cjs/polyfill/RTCIceCandidate.cjs +132 -0
  38. package/dist/cjs/polyfill/RTCIceCandidate.cjs.map +1 -0
  39. package/dist/cjs/polyfill/RTCIceTransport.cjs +94 -0
  40. package/dist/cjs/polyfill/RTCIceTransport.cjs.map +1 -0
  41. package/dist/cjs/polyfill/RTCPeerConnection.cjs +434 -0
  42. package/dist/cjs/polyfill/RTCPeerConnection.cjs.map +1 -0
  43. package/dist/cjs/polyfill/RTCSctpTransport.cjs +59 -0
  44. package/dist/cjs/polyfill/RTCSctpTransport.cjs.map +1 -0
  45. package/dist/cjs/polyfill/RTCSessionDescription.cjs +45 -0
  46. package/dist/cjs/polyfill/RTCSessionDescription.cjs.map +1 -0
  47. package/dist/cjs/polyfill/index.cjs +42 -0
  48. package/dist/cjs/polyfill/index.cjs.map +1 -0
  49. package/dist/esm/index.mjs +8 -0
  50. package/dist/esm/index.mjs.map +1 -0
  51. package/dist/esm/lib/datachannel-stream.mjs +78 -0
  52. package/dist/esm/lib/datachannel-stream.mjs.map +1 -0
  53. package/dist/esm/lib/index.mjs +62 -0
  54. package/dist/esm/lib/index.mjs.map +1 -0
  55. package/dist/esm/lib/node-datachannel.mjs +12 -0
  56. package/dist/esm/lib/node-datachannel.mjs.map +1 -0
  57. package/dist/esm/lib/websocket-server.mjs +43 -0
  58. package/dist/esm/lib/websocket-server.mjs.map +1 -0
  59. package/dist/esm/lib/websocket.mjs +6 -0
  60. package/dist/esm/lib/websocket.mjs.map +1 -0
  61. package/dist/esm/polyfill/Events.mjs +82 -0
  62. package/dist/esm/polyfill/Events.mjs.map +1 -0
  63. package/dist/esm/polyfill/Exception.mjs +28 -0
  64. package/dist/esm/polyfill/Exception.mjs.map +1 -0
  65. package/dist/esm/polyfill/RTCCertificate.mjs +30 -0
  66. package/dist/esm/polyfill/RTCCertificate.mjs.map +1 -0
  67. package/dist/esm/polyfill/RTCDataChannel.mjs +210 -0
  68. package/dist/esm/polyfill/RTCDataChannel.mjs.map +1 -0
  69. package/dist/esm/polyfill/RTCDtlsTransport.mjs +49 -0
  70. package/dist/esm/polyfill/RTCDtlsTransport.mjs.map +1 -0
  71. package/dist/esm/polyfill/RTCError.mjs +79 -0
  72. package/dist/esm/polyfill/RTCError.mjs.map +1 -0
  73. package/dist/esm/polyfill/RTCIceCandidate.mjs +128 -0
  74. package/dist/esm/polyfill/RTCIceCandidate.mjs.map +1 -0
  75. package/dist/esm/polyfill/RTCIceTransport.mjs +89 -0
  76. package/dist/esm/polyfill/RTCIceTransport.mjs.map +1 -0
  77. package/dist/esm/polyfill/RTCPeerConnection.mjs +430 -0
  78. package/dist/esm/polyfill/RTCPeerConnection.mjs.map +1 -0
  79. package/dist/esm/polyfill/RTCSctpTransport.mjs +55 -0
  80. package/dist/esm/polyfill/RTCSctpTransport.mjs.map +1 -0
  81. package/dist/esm/polyfill/RTCSessionDescription.mjs +41 -0
  82. package/dist/esm/polyfill/RTCSessionDescription.mjs.map +1 -0
  83. package/dist/esm/polyfill/index.mjs +27 -0
  84. package/dist/esm/polyfill/index.mjs.map +1 -0
  85. package/dist/types/lib/datachannel-stream.d.ts +24 -0
  86. package/dist/types/lib/index.d.ts +235 -0
  87. package/dist/types/lib/types.d.ts +118 -0
  88. package/dist/types/lib/websocket-server.d.ts +13 -0
  89. package/dist/types/lib/websocket.d.ts +25 -0
  90. package/dist/types/polyfill/Events.d.ts +15 -0
  91. package/dist/types/polyfill/RTCCertificate.d.ts +9 -0
  92. package/dist/types/polyfill/RTCDataChannel.d.ts +29 -0
  93. package/dist/types/polyfill/RTCDtlsTransport.d.ts +15 -0
  94. package/dist/types/polyfill/RTCError.d.ts +17 -0
  95. package/dist/types/polyfill/RTCIceCandidate.d.ts +21 -0
  96. package/dist/types/polyfill/RTCIceTransport.d.ts +30 -0
  97. package/dist/types/polyfill/RTCPeerConnection.d.ts +64 -0
  98. package/dist/types/polyfill/RTCSctpTransport.d.ts +15 -0
  99. package/dist/types/polyfill/RTCSessionDescription.d.ts +10 -0
  100. package/dist/types/polyfill/index.d.ts +26 -0
  101. package/jest.config.ts +14 -0
  102. package/package.json +121 -0
  103. package/rollup.config.mjs +72 -0
  104. package/src/cpp/data-channel-wrapper.cpp +530 -0
  105. package/src/cpp/data-channel-wrapper.h +63 -0
  106. package/src/cpp/ice-udp-mux-listener-wrapper.cpp +157 -0
  107. package/src/cpp/ice-udp-mux-listener-wrapper.h +43 -0
  108. package/src/cpp/main.cpp +58 -0
  109. package/src/cpp/media-audio-wrapper.cpp +457 -0
  110. package/src/cpp/media-audio-wrapper.h +52 -0
  111. package/src/cpp/media-av1packetization.cpp +24 -0
  112. package/src/cpp/media-av1packetization.h +11 -0
  113. package/src/cpp/media-av1rtppacketizer-wrapper.cpp +126 -0
  114. package/src/cpp/media-av1rtppacketizer-wrapper.h +29 -0
  115. package/src/cpp/media-direction.cpp +43 -0
  116. package/src/cpp/media-direction.h +10 -0
  117. package/src/cpp/media-h264rtppacketizer-wrapper.cpp +126 -0
  118. package/src/cpp/media-h264rtppacketizer-wrapper.h +30 -0
  119. package/src/cpp/media-h265rtppacketizer-wrapper.cpp +126 -0
  120. package/src/cpp/media-h265rtppacketizer-wrapper.h +30 -0
  121. package/src/cpp/media-h26xseparator.cpp +32 -0
  122. package/src/cpp/media-h26xseparator.h +11 -0
  123. package/src/cpp/media-mediahandler-helper.cpp +31 -0
  124. package/src/cpp/media-mediahandler-helper.h +11 -0
  125. package/src/cpp/media-pacinghandler-wrapper.cpp +79 -0
  126. package/src/cpp/media-pacinghandler-wrapper.h +28 -0
  127. package/src/cpp/media-rtcpnackresponder-wrapper.cpp +68 -0
  128. package/src/cpp/media-rtcpnackresponder-wrapper.h +28 -0
  129. package/src/cpp/media-rtcpreceivingsession-wrapper.cpp +57 -0
  130. package/src/cpp/media-rtcpreceivingsession-wrapper.h +28 -0
  131. package/src/cpp/media-rtcpsrreporter-wrapper.cpp +93 -0
  132. package/src/cpp/media-rtcpsrreporter-wrapper.h +30 -0
  133. package/src/cpp/media-rtppacketizationconfig-wrapper.cpp +167 -0
  134. package/src/cpp/media-rtppacketizationconfig-wrapper.h +35 -0
  135. package/src/cpp/media-rtppacketizer-wrapper.cpp +95 -0
  136. package/src/cpp/media-rtppacketizer-wrapper.h +30 -0
  137. package/src/cpp/media-track-wrapper.cpp +458 -0
  138. package/src/cpp/media-track-wrapper.h +61 -0
  139. package/src/cpp/media-video-wrapper.cpp +526 -0
  140. package/src/cpp/media-video-wrapper.h +56 -0
  141. package/src/cpp/peer-connection-wrapper.cpp +1298 -0
  142. package/src/cpp/peer-connection-wrapper.h +89 -0
  143. package/src/cpp/rtc-wrapper.cpp +205 -0
  144. package/src/cpp/rtc-wrapper.h +24 -0
  145. package/src/cpp/thread-safe-callback.cpp +57 -0
  146. package/src/cpp/thread-safe-callback.h +47 -0
  147. package/src/cpp/web-socket-server-wrapper.cpp +275 -0
  148. package/src/cpp/web-socket-server-wrapper.h +41 -0
  149. package/src/cpp/web-socket-wrapper.cpp +796 -0
  150. package/src/cpp/web-socket-wrapper.h +63 -0
  151. package/src/index.ts +9 -0
  152. package/src/lib/datachannel-stream.ts +100 -0
  153. package/src/lib/index.ts +283 -0
  154. package/src/lib/node-datachannel.ts +3 -0
  155. package/src/lib/types.ts +168 -0
  156. package/src/lib/websocket-server.ts +37 -0
  157. package/src/lib/websocket.ts +26 -0
  158. package/src/polyfill/Events.ts +82 -0
  159. package/src/polyfill/Exception.ts +37 -0
  160. package/src/polyfill/README.md +41 -0
  161. package/src/polyfill/RTCCertificate.ts +21 -0
  162. package/src/polyfill/RTCDataChannel.ts +225 -0
  163. package/src/polyfill/RTCDtlsTransport.ts +46 -0
  164. package/src/polyfill/RTCError.ts +78 -0
  165. package/src/polyfill/RTCIceCandidate.ts +128 -0
  166. package/src/polyfill/RTCIceTransport.ts +90 -0
  167. package/src/polyfill/RTCPeerConnection.ts +527 -0
  168. package/src/polyfill/RTCSctpTransport.ts +51 -0
  169. package/src/polyfill/RTCSessionDescription.ts +41 -0
  170. package/src/polyfill/index.ts +38 -0
  171. package/tsconfig.json +21 -0
@@ -0,0 +1,157 @@
1
+ #include "ice-udp-mux-listener-wrapper.h"
2
+
3
+ #include "plog/Log.h"
4
+
5
+ #include <cctype>
6
+
7
+ Napi::FunctionReference IceUdpMuxListenerWrapper::constructor = Napi::FunctionReference();
8
+ std::unordered_set<IceUdpMuxListenerWrapper *> IceUdpMuxListenerWrapper::instances;
9
+
10
+ void IceUdpMuxListenerWrapper::StopAll()
11
+ {
12
+ PLOG_DEBUG << "IceUdpMuxListenerWrapper StopAll() called";
13
+ auto copy(instances);
14
+ for (auto inst : copy)
15
+ inst->doCleanup();
16
+ }
17
+
18
+ Napi::Object IceUdpMuxListenerWrapper::Init(Napi::Env env, Napi::Object exports)
19
+ {
20
+ Napi::HandleScope scope(env);
21
+
22
+ Napi::Function func =
23
+ DefineClass(env, "IceUdpMuxListener",
24
+ {InstanceMethod("stop", &IceUdpMuxListenerWrapper::stop),
25
+ InstanceMethod("onUnhandledStunRequest", &IceUdpMuxListenerWrapper::onUnhandledStunRequest),
26
+ InstanceMethod("port", &IceUdpMuxListenerWrapper::port),
27
+ InstanceMethod("address", &IceUdpMuxListenerWrapper::address)});
28
+
29
+ // If this is not the first call, we don't want to reassign the constructor (hot-reload problem)
30
+ if (constructor.IsEmpty())
31
+ {
32
+ constructor = Napi::Persistent(func);
33
+ constructor.SuppressDestruct();
34
+ }
35
+
36
+ exports.Set("IceUdpMuxListener", func);
37
+ return exports;
38
+ }
39
+
40
+ IceUdpMuxListenerWrapper::IceUdpMuxListenerWrapper(const Napi::CallbackInfo &info)
41
+ : Napi::ObjectWrap<IceUdpMuxListenerWrapper>(info)
42
+ {
43
+ PLOG_DEBUG << "IceUdpMuxListenerWrapper Constructor called";
44
+ Napi::Env env = info.Env();
45
+ int length = info.Length();
46
+
47
+ // We expect (Number, String?) as param
48
+ if (length > 0 && info[0].IsNumber())
49
+ {
50
+ // Port
51
+ mPort = info[0].As<Napi::Number>().ToNumber().Uint32Value();
52
+ }
53
+ else
54
+ {
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
+ {
61
+ // Address
62
+ mAddress = info[1].As<Napi::String>().ToString();
63
+ }
64
+
65
+ iceUdpMuxListenerPtr = std::make_unique<rtc::IceUdpMuxListener>(mPort, mAddress);
66
+ instances.insert(this);
67
+ }
68
+
69
+ IceUdpMuxListenerWrapper::~IceUdpMuxListenerWrapper()
70
+ {
71
+ PLOG_DEBUG << "IceUdpMuxListenerWrapper Destructor called";
72
+ doCleanup();
73
+ }
74
+
75
+ void IceUdpMuxListenerWrapper::doCleanup()
76
+ {
77
+ PLOG_DEBUG << "IceUdpMuxListenerWrapper::doCleanup() called";
78
+
79
+ if (iceUdpMuxListenerPtr)
80
+ {
81
+ iceUdpMuxListenerPtr->stop();
82
+ iceUdpMuxListenerPtr.reset();
83
+ }
84
+
85
+ mOnUnhandledStunRequestCallback.reset();
86
+ instances.erase(this);
87
+ }
88
+
89
+ Napi::Value IceUdpMuxListenerWrapper::port(const Napi::CallbackInfo &info)
90
+ {
91
+ Napi::Env env = info.Env();
92
+
93
+ return Napi::Number::New(env, mPort);
94
+ }
95
+
96
+ Napi::Value IceUdpMuxListenerWrapper::address(const Napi::CallbackInfo &info)
97
+ {
98
+ Napi::Env env = info.Env();
99
+
100
+ if (!mAddress.has_value())
101
+ {
102
+ return env.Undefined();
103
+ }
104
+
105
+ return Napi::String::New(env, mAddress.value());
106
+ }
107
+
108
+ void IceUdpMuxListenerWrapper::stop(const Napi::CallbackInfo &info)
109
+ {
110
+ PLOG_DEBUG << "IceUdpMuxListenerWrapper::stop() called";
111
+ doCleanup();
112
+ }
113
+
114
+ void IceUdpMuxListenerWrapper::onUnhandledStunRequest(const Napi::CallbackInfo &info)
115
+ {
116
+ PLOG_DEBUG << "IceUdpMuxListenerWrapper::onUnhandledStunRequest() called";
117
+ Napi::Env env = info.Env();
118
+ int length = info.Length();
119
+
120
+ if (!iceUdpMuxListenerPtr)
121
+ {
122
+ Napi::Error::New(env, "IceUdpMuxListenerWrapper::onUnhandledStunRequest() called on destroyed IceUdpMuxListener")
123
+ .ThrowAsJavaScriptException();
124
+ return;
125
+ }
126
+
127
+ if (length < 1 || !info[0].IsFunction())
128
+ {
129
+ Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
130
+ return;
131
+ }
132
+
133
+ // Callback
134
+ mOnUnhandledStunRequestCallback = std::make_unique<ThreadSafeCallback>(info[0].As<Napi::Function>());
135
+
136
+ iceUdpMuxListenerPtr->OnUnhandledStunRequest(
137
+ [&](rtc::IceUdpMuxRequest request)
138
+ {
139
+ PLOG_DEBUG << "IceUdpMuxListenerWrapper::onUnhandledStunRequest() IceUdpMuxCallback call(1)";
140
+
141
+ if (mOnUnhandledStunRequestCallback)
142
+ {
143
+ mOnUnhandledStunRequestCallback->call(
144
+ [request = std::move(request)](Napi::Env env, std::vector<napi_value> &args)
145
+ {
146
+ Napi::Object reqObj = Napi::Object::New(env);
147
+ reqObj.Set("ufrag", request.remoteUfrag.c_str());
148
+ reqObj.Set("host", request.remoteAddress.c_str());
149
+ reqObj.Set("port", request.remotePort);
150
+
151
+ args = {reqObj};
152
+ });
153
+ }
154
+
155
+ PLOG_DEBUG << "IceUdpMuxListenerWrapper::onUnhandledStunRequest() IceUdpMuxCallback call(2)";
156
+ });
157
+ }
@@ -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
@@ -0,0 +1,58 @@
1
+ #include <napi.h>
2
+ #include "rtc-wrapper.h"
3
+ #include "peer-connection-wrapper.h"
4
+ #include "data-channel-wrapper.h"
5
+ #include "ice-udp-mux-listener-wrapper.h"
6
+
7
+ #if RTC_ENABLE_MEDIA == 1
8
+ #include "media-av1rtppacketizer-wrapper.h"
9
+ #include "media-h264rtppacketizer-wrapper.h"
10
+ #include "media-h265rtppacketizer-wrapper.h"
11
+ #include "media-pacinghandler-wrapper.h"
12
+ #include "media-rtcpnackresponder-wrapper.h"
13
+ #include "media-rtcpreceivingsession-wrapper.h"
14
+ #include "media-rtcpsrreporter-wrapper.h"
15
+ #include "media-rtppacketizationconfig-wrapper.h"
16
+ #include "media-rtppacketizer-wrapper.h"
17
+ #include "media-track-wrapper.h"
18
+ #include "media-video-wrapper.h"
19
+ #include "media-audio-wrapper.h"
20
+ #endif
21
+
22
+ #if RTC_ENABLE_WEBSOCKET == 1
23
+ #include "web-socket-wrapper.h"
24
+ #include "web-socket-server-wrapper.h"
25
+ #endif
26
+
27
+ Napi::Object InitAll(Napi::Env env, Napi::Object exports)
28
+ {
29
+ RtcWrapper::Init(env, exports);
30
+
31
+ #if RTC_ENABLE_MEDIA == 1
32
+ AV1RtpPacketizerWrapper::Init(env, exports);
33
+ H264RtpPacketizerWrapper::Init(env, exports);
34
+ H265RtpPacketizerWrapper::Init(env, exports);
35
+ PacingHandlerWrapper::Init(env, exports);
36
+ RtcpNackResponderWrapper::Init(env, exports);
37
+ RtcpReceivingSessionWrapper::Init(env, exports);
38
+ RtcpSrReporterWrapper::Init(env, exports);
39
+ RtpPacketizationConfigWrapper::Init(env, exports);
40
+ RtpPacketizerWrapper::Init(env, exports);
41
+ TrackWrapper::Init(env, exports);
42
+ VideoWrapper::Init(env, exports);
43
+ AudioWrapper::Init(env, exports);
44
+ #endif
45
+
46
+ DataChannelWrapper::Init(env, exports);
47
+ IceUdpMuxListenerWrapper::Init(env, exports);
48
+ PeerConnectionWrapper::Init(env, exports);
49
+
50
+ #if RTC_ENABLE_WEBSOCKET == 1
51
+ WebSocketWrapper::Init(env, exports);
52
+ WebSocketServerWrapper::Init(env, exports);
53
+ #endif
54
+
55
+ return exports;
56
+ }
57
+
58
+ NODE_API_MODULE(nodeDataChannel, InitAll)
@@ -0,0 +1,457 @@
1
+ #include "media-audio-wrapper.h"
2
+ #include "media-direction.h"
3
+
4
+ Napi::FunctionReference AudioWrapper::constructor = Napi::FunctionReference();
5
+ std::unordered_set<AudioWrapper *> AudioWrapper::instances;
6
+
7
+ Napi::Object AudioWrapper::Init(Napi::Env env, Napi::Object exports)
8
+ {
9
+ Napi::HandleScope scope(env);
10
+
11
+ Napi::Function func = DefineClass(env, "Audio",
12
+ {
13
+ InstanceValue("media-type-audio", Napi::Boolean::New(env, true)),
14
+ InstanceMethod("addAudioCodec", &AudioWrapper::addAudioCodec),
15
+ InstanceMethod("addOpusCodec", &AudioWrapper::addOpusCodec),
16
+ InstanceMethod("direction", &AudioWrapper::direction),
17
+ InstanceMethod("generateSdp", &AudioWrapper::generateSdp),
18
+ InstanceMethod("mid", &AudioWrapper::mid),
19
+ InstanceMethod("setDirection", &AudioWrapper::setDirection),
20
+ InstanceMethod("description", &AudioWrapper::description),
21
+ InstanceMethod("removeFormat", &AudioWrapper::removeFormat),
22
+ InstanceMethod("addSSRC", &AudioWrapper::addSSRC),
23
+ InstanceMethod("removeSSRC", &AudioWrapper::removeSSRC),
24
+ InstanceMethod("replaceSSRC", &AudioWrapper::replaceSSRC),
25
+ InstanceMethod("hasSSRC", &AudioWrapper::hasSSRC),
26
+ InstanceMethod("getSSRCs", &AudioWrapper::getSSRCs),
27
+ InstanceMethod("getCNameForSsrc", &AudioWrapper::getCNameForSsrc),
28
+ InstanceMethod("setBitrate", &AudioWrapper::setBitrate),
29
+ InstanceMethod("getBitrate", &AudioWrapper::getBitrate),
30
+ InstanceMethod("hasPayloadType", &AudioWrapper::hasPayloadType),
31
+ InstanceMethod("addRTXCodec", &AudioWrapper::addRTXCodec),
32
+ InstanceMethod("addRTPMap", &AudioWrapper::addRTPMap),
33
+ InstanceMethod("parseSdpLine", &AudioWrapper::parseSdpLine),
34
+ });
35
+
36
+ // If this is not the first call, we don't want to reassign the constructor (hot-reload problem)
37
+ if (constructor.IsEmpty())
38
+ {
39
+ constructor = Napi::Persistent(func);
40
+ constructor.SuppressDestruct();
41
+ }
42
+
43
+ exports.Set("Audio", func);
44
+ return exports;
45
+ }
46
+
47
+ AudioWrapper::AudioWrapper(const Napi::CallbackInfo &info) : Napi::ObjectWrap<AudioWrapper>(info)
48
+ {
49
+ Napi::Env env = info.Env();
50
+ int length = info.Length();
51
+
52
+ std::string mid = "audio";
53
+ rtc::Description::Direction dir = rtc::Description::Direction::SendOnly;
54
+
55
+ // optional
56
+ if (length > 0)
57
+ {
58
+ if (!info[0].IsString())
59
+ {
60
+ Napi::TypeError::New(env, "mid (String) expected").ThrowAsJavaScriptException();
61
+ return;
62
+ }
63
+ mid = info[0].As<Napi::String>().ToString();
64
+ }
65
+
66
+ // ootional
67
+ if (length > 1)
68
+ {
69
+ if (!info[1].IsString())
70
+ {
71
+ Napi::TypeError::New(env, "direction (String) expected").ThrowAsJavaScriptException();
72
+ return;
73
+ }
74
+
75
+ std::string dirAsStr = info[1].As<Napi::String>().ToString();
76
+ dir = strToDirection(dirAsStr);
77
+ }
78
+
79
+ mAudioPtr = std::make_unique<rtc::Description::Audio>(mid, dir);
80
+
81
+ instances.insert(this);
82
+ }
83
+
84
+ AudioWrapper::~AudioWrapper()
85
+ {
86
+ mAudioPtr.reset();
87
+ instances.erase(this);
88
+ }
89
+
90
+ rtc::Description::Audio AudioWrapper::getAudioInstance() { return *(mAudioPtr.get()); }
91
+
92
+ void AudioWrapper::addAudioCodec(const Napi::CallbackInfo &info)
93
+ {
94
+ Napi::Env env = info.Env();
95
+ int length = info.Length();
96
+
97
+ if (length < 2 || !info[0].IsNumber() || !info[1].IsString())
98
+ {
99
+ Napi::TypeError::New(env, "We expect (Number, String, String[optional]) as param").ThrowAsJavaScriptException();
100
+ return;
101
+ }
102
+
103
+ int payloadType = info[0].As<Napi::Number>().ToNumber();
104
+ std::string codec = info[1].As<Napi::String>().ToString();
105
+ std::optional<std::string> profile = std::nullopt;
106
+
107
+ if (length > 2)
108
+ {
109
+ if (!info[2].IsString())
110
+ {
111
+ Napi::TypeError::New(env, "profile (String) expected").ThrowAsJavaScriptException();
112
+ return;
113
+ }
114
+ profile = info[2].As<Napi::String>().ToString();
115
+ }
116
+
117
+ mAudioPtr->addAudioCodec(payloadType, codec, profile);
118
+ }
119
+
120
+ void AudioWrapper::addOpusCodec(const Napi::CallbackInfo &info)
121
+ {
122
+ Napi::Env env = info.Env();
123
+ int length = info.Length();
124
+
125
+ if (length < 1 || !info[0].IsNumber())
126
+ {
127
+ Napi::TypeError::New(env, "We expect (Number) as param").ThrowAsJavaScriptException();
128
+ return;
129
+ }
130
+
131
+ int payloadType = info[0].As<Napi::Number>().ToNumber();
132
+ std::optional<std::string> profile = rtc::DEFAULT_OPUS_AUDIO_PROFILE;
133
+
134
+ if (length > 1)
135
+ {
136
+ if (!info[1].IsString())
137
+ {
138
+ Napi::TypeError::New(env, "profile (String) expected").ThrowAsJavaScriptException();
139
+ return;
140
+ }
141
+ profile = info[1].As<Napi::String>().ToString();
142
+ }
143
+
144
+ mAudioPtr->addOpusCodec(payloadType, profile);
145
+ }
146
+
147
+ Napi::Value AudioWrapper::direction(const Napi::CallbackInfo &info)
148
+ {
149
+ Napi::Env env = info.Env();
150
+ return Napi::String::New(env, directionToStr(mAudioPtr->direction()));
151
+ }
152
+
153
+ Napi::Value AudioWrapper::generateSdp(const Napi::CallbackInfo &info)
154
+ {
155
+ Napi::Env env = info.Env();
156
+ int length = info.Length();
157
+
158
+ if (length < 3 || !info[0].IsString() || !info[1].IsString() || !info[2].IsNumber())
159
+ {
160
+ Napi::TypeError::New(env, "We expect (String, String, Number) as param").ThrowAsJavaScriptException();
161
+ return Napi::String::New(env, "");
162
+ }
163
+
164
+ std::string eol = info[0].As<Napi::String>().ToString();
165
+ std::string addr = info[1].As<Napi::String>().ToString();
166
+ uint16_t port = info[2].As<Napi::Number>().Uint32Value();
167
+
168
+ return Napi::String::New(env, mAudioPtr->generateSdp(eol, addr, port));
169
+ }
170
+
171
+ Napi::Value AudioWrapper::mid(const Napi::CallbackInfo &info)
172
+ {
173
+ Napi::Env env = info.Env();
174
+ return Napi::String::New(env, mAudioPtr->mid());
175
+ }
176
+
177
+ void AudioWrapper::setDirection(const Napi::CallbackInfo &info)
178
+ {
179
+ Napi::Env env = info.Env();
180
+ int length = info.Length();
181
+
182
+ if (length < 1 || !info[0].IsString())
183
+ {
184
+ Napi::TypeError::New(env, "We expect (String) as param").ThrowAsJavaScriptException();
185
+ return;
186
+ }
187
+
188
+ std::string dirAsStr = info[0].As<Napi::String>().ToString();
189
+ rtc::Description::Direction dir = strToDirection(dirAsStr);
190
+ mAudioPtr->setDirection(dir);
191
+ }
192
+
193
+ Napi::Value AudioWrapper::description(const Napi::CallbackInfo &info)
194
+ {
195
+ Napi::Env env = info.Env();
196
+ return Napi::String::New(env, mAudioPtr->description());
197
+ }
198
+
199
+ void AudioWrapper::removeFormat(const Napi::CallbackInfo &info)
200
+ {
201
+ Napi::Env env = info.Env();
202
+ int length = info.Length();
203
+
204
+ if (length < 1 || !info[0].IsString())
205
+ {
206
+ Napi::TypeError::New(env, "We expect (String) as param").ThrowAsJavaScriptException();
207
+ return;
208
+ }
209
+
210
+ std::string fmt = info[0].As<Napi::String>().ToString();
211
+
212
+ mAudioPtr->removeFormat(fmt);
213
+ }
214
+
215
+ void AudioWrapper::addSSRC(const Napi::CallbackInfo &info)
216
+ {
217
+ Napi::Env env = info.Env();
218
+ int length = info.Length();
219
+
220
+ if (length < 1 || !info[0].IsNumber())
221
+ {
222
+ Napi::TypeError::New(env, "We expect (Number, String[optional], String[optional], String[optional]) as param")
223
+ .ThrowAsJavaScriptException();
224
+ return;
225
+ }
226
+
227
+ uint32_t ssrc = static_cast<uint32_t>(info[0].As<Napi::Number>().ToNumber());
228
+ std::optional<std::string> name;
229
+ std::optional<std::string> msid = std::nullopt;
230
+ std::optional<std::string> trackID = std::nullopt;
231
+
232
+ if (length > 1)
233
+ {
234
+ if (!info[1].IsString())
235
+ {
236
+ Napi::TypeError::New(env, "name as String expected").ThrowAsJavaScriptException();
237
+ return;
238
+ }
239
+ name = info[1].As<Napi::String>().ToString();
240
+ }
241
+
242
+ if (length > 2)
243
+ {
244
+ if (!info[2].IsString())
245
+ {
246
+ Napi::TypeError::New(env, "msid as String expected").ThrowAsJavaScriptException();
247
+ return;
248
+ }
249
+ msid = info[2].As<Napi::String>().ToString();
250
+ }
251
+
252
+ if (length > 3)
253
+ {
254
+ if (!info[3].IsString())
255
+ {
256
+ Napi::TypeError::New(env, "trackID as String expected").ThrowAsJavaScriptException();
257
+ return;
258
+ }
259
+ trackID = info[3].As<Napi::String>().ToString();
260
+ }
261
+
262
+ mAudioPtr->addSSRC(ssrc, name, msid, trackID);
263
+ }
264
+
265
+ void AudioWrapper::removeSSRC(const Napi::CallbackInfo &info)
266
+ {
267
+ Napi::Env env = info.Env();
268
+ int length = info.Length();
269
+
270
+ if (length < 1 || !info[0].IsNumber())
271
+ {
272
+ Napi::TypeError::New(env, "We expect (Number) as param").ThrowAsJavaScriptException();
273
+ return;
274
+ }
275
+
276
+ uint32_t ssrc = static_cast<uint32_t>(info[0].As<Napi::Number>().ToNumber());
277
+
278
+ mAudioPtr->removeSSRC(ssrc);
279
+ }
280
+
281
+ void AudioWrapper::replaceSSRC(const Napi::CallbackInfo &info)
282
+ {
283
+ Napi::Env env = info.Env();
284
+ int length = info.Length();
285
+
286
+ if (length < 2 || !info[0].IsNumber() || !info[1].IsNumber())
287
+ {
288
+ Napi::TypeError::New(env,
289
+ "We expect (Number, Number, String[optional], String[optional], String[optional]) as param")
290
+ .ThrowAsJavaScriptException();
291
+ return;
292
+ }
293
+
294
+ uint32_t ssrc = static_cast<uint32_t>(info[0].As<Napi::Number>().ToNumber());
295
+ uint32_t oldSsrc = static_cast<uint32_t>(info[1].As<Napi::Number>().ToNumber());
296
+ std::optional<std::string> name;
297
+ std::optional<std::string> msid = std::nullopt;
298
+ std::optional<std::string> trackID = std::nullopt;
299
+
300
+ if (length > 2)
301
+ {
302
+ if (!info[2].IsString())
303
+ {
304
+ Napi::TypeError::New(env, "name as String expected").ThrowAsJavaScriptException();
305
+ return;
306
+ }
307
+ name = info[2].As<Napi::String>().ToString();
308
+ }
309
+
310
+ if (length > 3)
311
+ {
312
+ if (!info[3].IsString())
313
+ {
314
+ Napi::TypeError::New(env, "msid as String expected").ThrowAsJavaScriptException();
315
+ return;
316
+ }
317
+ msid = info[3].As<Napi::String>().ToString();
318
+ }
319
+
320
+ if (length > 4)
321
+ {
322
+ if (!info[4].IsString())
323
+ {
324
+ Napi::TypeError::New(env, "trackID as String expected").ThrowAsJavaScriptException();
325
+ return;
326
+ }
327
+ trackID = info[4].As<Napi::String>().ToString();
328
+ }
329
+
330
+ mAudioPtr->replaceSSRC(oldSsrc, ssrc, name, msid, trackID);
331
+ }
332
+
333
+ Napi::Value AudioWrapper::hasSSRC(const Napi::CallbackInfo &info)
334
+ {
335
+ Napi::Env env = info.Env();
336
+ int length = info.Length();
337
+
338
+ if (length < 1 || !info[0].IsNumber())
339
+ {
340
+ Napi::TypeError::New(env, "We expect (Number) as param").ThrowAsJavaScriptException();
341
+ return env.Null();
342
+ }
343
+
344
+ uint32_t ssrc = static_cast<uint32_t>(info[0].As<Napi::Number>().ToNumber());
345
+
346
+ return Napi::Boolean::New(env, mAudioPtr->hasSSRC(ssrc));
347
+ }
348
+
349
+ Napi::Value AudioWrapper::getSSRCs(const Napi::CallbackInfo &info)
350
+ {
351
+ Napi::Env env = info.Env();
352
+
353
+ auto list = mAudioPtr->getSSRCs();
354
+
355
+ Napi::Uint32Array napiArr = Napi::Uint32Array::New(env, list.size());
356
+ for (size_t i = 0; i < list.size(); i++)
357
+ napiArr[i] = list[i];
358
+
359
+ return napiArr;
360
+ }
361
+
362
+ Napi::Value AudioWrapper::getCNameForSsrc(const Napi::CallbackInfo &info)
363
+ {
364
+ Napi::Env env = info.Env();
365
+ int length = info.Length();
366
+
367
+ if (length < 1 || !info[0].IsNumber())
368
+ {
369
+ Napi::TypeError::New(env, "We expect (Number) as param").ThrowAsJavaScriptException();
370
+ return env.Null();
371
+ }
372
+
373
+ uint32_t ssrc = static_cast<uint32_t>(info[0].As<Napi::Number>().ToNumber());
374
+
375
+ std::optional<std::string> name = mAudioPtr->getCNameForSsrc(ssrc);
376
+
377
+ if (!name.has_value())
378
+ return env.Null();
379
+
380
+ return Napi::String::New(env, name.value());
381
+ }
382
+
383
+ void AudioWrapper::setBitrate(const Napi::CallbackInfo &info)
384
+ {
385
+ Napi::Env env = info.Env();
386
+ int length = info.Length();
387
+
388
+ if (length < 1 || !info[0].IsNumber())
389
+ {
390
+ Napi::TypeError::New(env, "We expect (Number) as param").ThrowAsJavaScriptException();
391
+ return;
392
+ }
393
+
394
+ unsigned int bitrate = static_cast<uint32_t>(info[0].As<Napi::Number>().ToNumber());
395
+ mAudioPtr->setBitrate(bitrate);
396
+ }
397
+
398
+ Napi::Value AudioWrapper::getBitrate(const Napi::CallbackInfo &info)
399
+ {
400
+
401
+ return Napi::Number::New(info.Env(), mAudioPtr->bitrate());
402
+ }
403
+
404
+ Napi::Value AudioWrapper::hasPayloadType(const Napi::CallbackInfo &info)
405
+ {
406
+ Napi::Env env = info.Env();
407
+ int length = info.Length();
408
+
409
+ if (length < 1 || !info[0].IsNumber())
410
+ {
411
+ Napi::TypeError::New(env, "We expect (Number) as param").ThrowAsJavaScriptException();
412
+ return env.Null();
413
+ }
414
+
415
+ int payloadType = static_cast<int>(info[0].As<Napi::Number>().ToNumber());
416
+
417
+ return Napi::Boolean::New(env, mAudioPtr->hasPayloadType(payloadType));
418
+ }
419
+
420
+ void AudioWrapper::addRTXCodec(const Napi::CallbackInfo &info)
421
+ {
422
+ Napi::Env env = info.Env();
423
+ int length = info.Length();
424
+
425
+ if (length < 3 || !info[0].IsNumber() || !info[1].IsNumber() || !info[2].IsNumber())
426
+ {
427
+ Napi::TypeError::New(env, "We expect (Number,Number,Number) as param").ThrowAsJavaScriptException();
428
+ return;
429
+ }
430
+
431
+ int payloadType = static_cast<int32_t>(info[0].As<Napi::Number>().ToNumber());
432
+ int originalPayloadType = static_cast<int32_t>(info[1].As<Napi::Number>().ToNumber());
433
+ unsigned int clockRate = static_cast<uint32_t>(info[2].As<Napi::Number>().ToNumber());
434
+
435
+ mAudioPtr->addRtxCodec(payloadType, originalPayloadType, clockRate);
436
+ }
437
+
438
+ void AudioWrapper::addRTPMap(const Napi::CallbackInfo &info)
439
+ {
440
+ // mAudioPtr->addRTPMap()
441
+ }
442
+
443
+ void AudioWrapper::parseSdpLine(const Napi::CallbackInfo &info)
444
+ {
445
+ Napi::Env env = info.Env();
446
+ int length = info.Length();
447
+
448
+ if (length < 1 || !info[0].IsString())
449
+ {
450
+ Napi::TypeError::New(env, "We expect (String) as param").ThrowAsJavaScriptException();
451
+ return;
452
+ }
453
+
454
+ std::string line = info[0].As<Napi::String>().ToString();
455
+
456
+ mAudioPtr->parseSdpLine(line);
457
+ }