uwebsockets 2.0.0 → 2.1.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.
Files changed (95) hide show
  1. package/Makefile +11 -0
  2. package/README.md +38 -44
  3. package/build.c +185 -0
  4. package/docs/Makefile +2 -0
  5. package/docs/generated/.nojekyll +1 -0
  6. package/docs/generated/assets/highlight.css +22 -0
  7. package/docs/generated/assets/main.js +4 -0
  8. package/docs/generated/assets/search.js +1 -0
  9. package/docs/generated/assets/style.css +1280 -0
  10. package/docs/generated/enums/ListenOptions.html +70 -0
  11. package/docs/generated/functions/App.html +94 -0
  12. package/docs/generated/functions/SSLApp.html +93 -0
  13. package/docs/generated/functions/getParts.html +95 -0
  14. package/docs/generated/functions/us_listen_socket_close.html +93 -0
  15. package/docs/generated/functions/us_socket_local_port.html +93 -0
  16. package/docs/generated/index.html +131 -0
  17. package/docs/generated/interfaces/AppOptions.html +115 -0
  18. package/docs/generated/interfaces/HttpRequest.html +204 -0
  19. package/docs/generated/interfaces/HttpResponse.html +400 -0
  20. package/docs/generated/interfaces/MultipartField.html +88 -0
  21. package/docs/generated/interfaces/TemplatedApp.html +595 -0
  22. package/docs/generated/interfaces/WebSocket.html +303 -0
  23. package/docs/generated/interfaces/WebSocketBehavior.html +331 -0
  24. package/docs/generated/interfaces/us_listen_socket.html +89 -0
  25. package/docs/generated/interfaces/us_socket.html +89 -0
  26. package/docs/generated/interfaces/us_socket_context_t.html +89 -0
  27. package/docs/generated/types/CompressOptions.html +84 -0
  28. package/docs/generated/types/RecognizedString.html +89 -0
  29. package/docs/generated/variables/DEDICATED_COMPRESSOR_128KB.html +84 -0
  30. package/docs/generated/variables/DEDICATED_COMPRESSOR_16KB.html +84 -0
  31. package/docs/generated/variables/DEDICATED_COMPRESSOR_256KB.html +84 -0
  32. package/docs/generated/variables/DEDICATED_COMPRESSOR_32KB.html +84 -0
  33. package/docs/generated/variables/DEDICATED_COMPRESSOR_3KB.html +84 -0
  34. package/docs/generated/variables/DEDICATED_COMPRESSOR_4KB.html +84 -0
  35. package/docs/generated/variables/DEDICATED_COMPRESSOR_64KB.html +84 -0
  36. package/docs/generated/variables/DEDICATED_COMPRESSOR_8KB.html +84 -0
  37. package/docs/generated/variables/DEDICATED_DECOMPRESSOR.html +84 -0
  38. package/docs/generated/variables/DEDICATED_DECOMPRESSOR_16KB.html +84 -0
  39. package/docs/generated/variables/DEDICATED_DECOMPRESSOR_1KB.html +84 -0
  40. package/docs/generated/variables/DEDICATED_DECOMPRESSOR_2KB.html +84 -0
  41. package/docs/generated/variables/DEDICATED_DECOMPRESSOR_32KB.html +84 -0
  42. package/docs/generated/variables/DEDICATED_DECOMPRESSOR_4KB.html +84 -0
  43. package/docs/generated/variables/DEDICATED_DECOMPRESSOR_512B.html +84 -0
  44. package/docs/generated/variables/DEDICATED_DECOMPRESSOR_8KB.html +84 -0
  45. package/docs/generated/variables/DISABLED.html +84 -0
  46. package/docs/generated/variables/SHARED_COMPRESSOR.html +84 -0
  47. package/docs/generated/variables/SHARED_DECOMPRESSOR.html +84 -0
  48. package/docs/index.d.ts +395 -0
  49. package/docs/report.pdf +0 -0
  50. package/docs/tsconfig.json +11 -0
  51. package/examples/AsyncFunction.js +43 -0
  52. package/examples/AutomaticPortSelection.js +20 -0
  53. package/examples/Backpressure.js +75 -0
  54. package/examples/Broadcast.js +39 -0
  55. package/examples/GracefulShutdown.js +39 -0
  56. package/examples/H3lloWorld.js +23 -0
  57. package/examples/Headers.js +31 -0
  58. package/examples/HelloWorld.js +18 -0
  59. package/examples/JsonPost.js +72 -0
  60. package/examples/ProxyProtocol.js +25 -0
  61. package/examples/PubSub.js +57 -0
  62. package/examples/RateLimit.js +69 -0
  63. package/examples/Router.js +30 -0
  64. package/examples/ServerName.js +34 -0
  65. package/examples/ServerSentEvents.js +48 -0
  66. package/examples/SlowReceiver.js +53 -0
  67. package/examples/Upgrade.js +51 -0
  68. package/examples/UpgradeAsync.js +80 -0
  69. package/examples/Upload.js +36 -0
  70. package/examples/VideoStreamer.js +115 -0
  71. package/examples/VideoStreamerSync.js +42 -0
  72. package/examples/WebSockets.js +37 -0
  73. package/examples/WorkerThreads.js +33 -0
  74. package/misc/Manycast latency comparison [lower is better].png +0 -0
  75. package/misc/addon.pro +24 -0
  76. package/misc/cert.pem +21 -0
  77. package/misc/chart.png +0 -0
  78. package/misc/features_strip.png +0 -0
  79. package/misc/host.pro +31 -0
  80. package/misc/key.pem +28 -0
  81. package/misc/logo.svg +1 -0
  82. package/misc/streaming.png +0 -0
  83. package/package.json +1 -1
  84. package/src/AppWrapper.h +734 -0
  85. package/src/HttpRequestWrapper.h +196 -0
  86. package/src/HttpResponseWrapper.h +463 -0
  87. package/src/Utilities.h +172 -0
  88. package/src/WebSocketWrapper.h +348 -0
  89. package/src/addon.cpp +437 -0
  90. package/src/host.cpp +115 -0
  91. package/src/uws.js +24 -0
  92. package/tests/Autobahn.js +102 -0
  93. package/tests/Hammer.js +203 -0
  94. package/tests/Makefile +2 -0
  95. package/tests/fuzzingclient.json +28 -0
package/src/addon.cpp ADDED
@@ -0,0 +1,437 @@
1
+ /*
2
+ * Authored by Alex Hultman, 2018-2020.
3
+ * Intellectual property of third-party.
4
+
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ /* We are only allowed to depend on µWS and V8 in this layer. */
19
+ #include "App.h"
20
+ #include "Http3App.h"
21
+
22
+ #include <iostream>
23
+ #include <vector>
24
+ #include <type_traits>
25
+
26
+ #include <v8.h>
27
+ using namespace v8;
28
+
29
+ #include "Utilities.h"
30
+ #include "WebSocketWrapper.h"
31
+ #include "HttpResponseWrapper.h"
32
+ #include "HttpRequestWrapper.h"
33
+ #include "AppWrapper.h"
34
+
35
+ #include <numeric>
36
+ #include <functional>
37
+
38
+ /* Todo: Apps should be freed once the GC says so BUT ALWAYS before freeing the loop */
39
+
40
+ #include "Multipart.h"
41
+
42
+ /* This function is somewhat of a simplifying wrapper that does not follow the C++ library.
43
+ * It takes a POST:ed body and contentType, and returns an array of parts if
44
+ * the request is a multipart request */
45
+ void uWS_getParts(const FunctionCallbackInfo<Value> &args) {
46
+
47
+ /* Because we mutate the strings, it is important that we get mutable input like
48
+ * ArrayBuffer or Buffer, not String! */
49
+ Isolate *isolate = args.GetIsolate();
50
+
51
+ NativeString body(args.GetIsolate(), args[0]);
52
+ if (body.isInvalid(args)) {
53
+ return;
54
+ }
55
+
56
+ NativeString contentType(args.GetIsolate(), args[1]);
57
+ if (contentType.isInvalid(args)) {
58
+ return;
59
+ }
60
+
61
+ uWS::MultipartParser mp(contentType.getString());
62
+ if (mp.isValid()) {
63
+ mp.setBody(body.getString());
64
+
65
+ std::pair<std::string_view, std::string_view> headers[10];
66
+
67
+ Local<Array> parts = Array::New(args.GetIsolate(), 0);
68
+
69
+ while (true) {
70
+ std::optional<std::string_view> optionalPart = mp.getNextPart(headers);
71
+ if (!optionalPart.has_value()) {
72
+ break;
73
+ }
74
+
75
+ std::string_view part = optionalPart.value();
76
+
77
+ Local<ArrayBuffer> partArrayBuffer = ArrayBuffer_New(isolate, (void *) part.data(), part.length());
78
+ /* Map is 30% faster in this case, but a static Object could be faster still */
79
+ Local<Object> partMap = Object::New(isolate);
80
+ partMap->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "data", NewStringType::kNormal).ToLocalChecked(), partArrayBuffer).IsNothing();
81
+
82
+ for (int i = 0; headers[i].first.length(); i++) {
83
+ /* We care about content-type and content-disposition */
84
+ if (headers[i].first == "content-type") {
85
+ partMap->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "type", NewStringType::kNormal).ToLocalChecked(), String::NewFromUtf8(isolate, headers[i].second.data(), NewStringType::kNormal, headers[i].second.length()).ToLocalChecked()).IsNothing();
86
+ } else if (headers[i].first == "content-disposition") {
87
+ /* Parse the parameters */
88
+ uWS::ParameterParser pp(headers[i].second);
89
+ while (true) {
90
+ auto [key, value] = pp.getKeyValue();
91
+ if (!key.length()) {
92
+ break;
93
+ }
94
+
95
+ // really anything that has both key and value and is not type or data?
96
+ if (key == "name" || key == "filename") {
97
+ partMap->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, key.data(), NewStringType::kNormal, key.length()).ToLocalChecked(), String::NewFromUtf8(isolate, value.data(), NewStringType::kNormal, value.length()).ToLocalChecked()).IsNothing();
98
+ }
99
+ }
100
+ }
101
+ }
102
+
103
+ parts->Set(isolate->GetCurrentContext(), parts->Length(), partMap).IsNothing();
104
+ }
105
+
106
+ args.GetReturnValue().Set(parts);
107
+ }
108
+
109
+ /* We'll return undefined on error */
110
+ }
111
+
112
+ /* Pass various undocumented configs */
113
+ void uWS_cfg(const FunctionCallbackInfo<Value> &args) {
114
+ NativeString key(args.GetIsolate(), args[0]);
115
+ if (key.isInvalid(args)) {
116
+ return;
117
+ }
118
+
119
+ int keyCode = std::accumulate(key.getString().begin(), key.getString().end(), 1, std::plus<int>());
120
+ if (keyCode == 656) {
121
+ uWS::Loop::get()->setSilent(true);
122
+ }
123
+ }
124
+
125
+ /* todo: Put this function and all inits of it in its own header */
126
+ void uWS_us_listen_socket_close(const FunctionCallbackInfo<Value> &args) {
127
+ // this should take int ssl first
128
+ us_listen_socket_close(0, (struct us_listen_socket_t *) External::Cast(*args[0])->Value());
129
+ }
130
+
131
+ void uWS_us_socket_local_port(const FunctionCallbackInfo<Value> &args) {
132
+ // this should take int ssl first, but us_socket_local_port doesn't use it so it doesn't matter
133
+ int port = us_socket_local_port(0, (struct us_socket_t *) External::Cast(*args[0])->Value());
134
+ args.GetReturnValue().Set(Integer::New(args.GetIsolate(), port));
135
+ }
136
+
137
+ /* Temporary KV store (doesn't belong here) */
138
+ #include <unordered_map>
139
+ #include <string>
140
+ #include <mutex>
141
+
142
+ std::unordered_map<std::string, std::unordered_map<std::string, std::string>> kvStoreString;
143
+ std::unordered_map<std::string, std::unordered_map<std::string, uint32_t>> kvStoreInteger;
144
+ std::mutex kvMutex;
145
+
146
+ // getString(key, collection)
147
+ void uWS_getString(const FunctionCallbackInfo<Value> &args) {
148
+ NativeString key(args.GetIsolate(), args[0]);
149
+ if (key.isInvalid(args)) {
150
+ return;
151
+ }
152
+
153
+ NativeString collection(args.GetIsolate(), args[1]);
154
+ if (collection.isInvalid(args)) {
155
+ return;
156
+ }
157
+
158
+ std::string value = kvStoreString[std::string(collection.getString())][std::string(key.getString())];
159
+
160
+ args.GetReturnValue().Set(String::NewFromUtf8(args.GetIsolate(), value.data(), NewStringType::kNormal, value.length()).ToLocalChecked());
161
+ }
162
+
163
+ void uWS_setString(const FunctionCallbackInfo<Value> &args) {
164
+ NativeString key(args.GetIsolate(), args[0]);
165
+ if (key.isInvalid(args)) {
166
+ return;
167
+ }
168
+ NativeString value(args.GetIsolate(), args[1]);
169
+ if (value.isInvalid(args)) {
170
+ return;
171
+ }
172
+
173
+ NativeString collection(args.GetIsolate(), args[2]);
174
+ if (collection.isInvalid(args)) {
175
+ return;
176
+ }
177
+
178
+ kvStoreString[std::string(collection.getString())][std::string(key.getString())] = value.getString();
179
+ }
180
+
181
+ void uWS_getInteger(const FunctionCallbackInfo<Value> &args) {
182
+ NativeString key(args.GetIsolate(), args[0]);
183
+ if (key.isInvalid(args)) {
184
+ return;
185
+ }
186
+
187
+ NativeString collection(args.GetIsolate(), args[1]);
188
+ if (collection.isInvalid(args)) {
189
+ return;
190
+ }
191
+
192
+ uint32_t value = kvStoreInteger[std::string(collection.getString())][std::string(key.getString())];
193
+
194
+ args.GetReturnValue().Set(Integer::New(args.GetIsolate(), value));
195
+ }
196
+
197
+ void uWS_setInteger(const FunctionCallbackInfo<Value> &args) {
198
+ NativeString key(args.GetIsolate(), args[0]);
199
+ if (key.isInvalid(args)) {
200
+ return;
201
+ }
202
+
203
+ uint32_t value = Local<Integer>::Cast(args[1])->Value();
204
+
205
+ NativeString collection(args.GetIsolate(), args[2]);
206
+ if (collection.isInvalid(args)) {
207
+ return;
208
+ }
209
+
210
+ kvStoreInteger[std::string(collection.getString())][std::string(key.getString())] = value;
211
+ }
212
+
213
+ void uWS_incInteger(const FunctionCallbackInfo<Value> &args) {
214
+ NativeString key(args.GetIsolate(), args[0]);
215
+ if (key.isInvalid(args)) {
216
+ return;
217
+ }
218
+
219
+ uint32_t change = Local<Integer>::Cast(args[1])->Value();
220
+
221
+ NativeString collection(args.GetIsolate(), args[2]);
222
+ if (collection.isInvalid(args)) {
223
+ return;
224
+ }
225
+
226
+ uint32_t value = kvStoreInteger[std::string(collection.getString())][std::string(key.getString())] += change;
227
+
228
+ args.GetReturnValue().Set(Integer::New(args.GetIsolate(), value));
229
+ }
230
+
231
+ /* This one will spike memory usage for large stores */
232
+ void uWS_getStringKeys(const FunctionCallbackInfo<Value> &args) {
233
+
234
+ NativeString collection(args.GetIsolate(), args[0]);
235
+ if (collection.isInvalid(args)) {
236
+ return;
237
+ }
238
+
239
+ Local<Array> stringKeys = Array::New(args.GetIsolate(), kvStoreString.size());
240
+
241
+ int offset = 0;
242
+
243
+ for (auto p : kvStoreString[std::string(collection.getString())]) {
244
+ stringKeys->Set(args.GetIsolate()->GetCurrentContext(), offset++, String::NewFromUtf8(args.GetIsolate(), p.first.data(), NewStringType::kNormal, p.first.length()).ToLocalChecked()).IsNothing();
245
+ }
246
+
247
+ args.GetReturnValue().Set(stringKeys);
248
+ }
249
+
250
+ void uWS_getIntegerKeys(const FunctionCallbackInfo<Value> &args) {
251
+
252
+ NativeString collection(args.GetIsolate(), args[0]);
253
+ if (collection.isInvalid(args)) {
254
+ return;
255
+ }
256
+
257
+ Local<Array> integerKeys = Array::New(args.GetIsolate(), kvStoreInteger.size());
258
+
259
+ int offset = 0;
260
+
261
+ for (auto p : kvStoreInteger[std::string(collection.getString())]) {
262
+ integerKeys->Set(args.GetIsolate()->GetCurrentContext(), offset++, String::NewFromUtf8(args.GetIsolate(), p.first.data(), NewStringType::kNormal, p.first.length()).ToLocalChecked()).IsNothing();
263
+ }
264
+
265
+ args.GetReturnValue().Set(integerKeys);
266
+ }
267
+
268
+ void uWS_deleteString(const FunctionCallbackInfo<Value> &args) {
269
+
270
+ NativeString key(args.GetIsolate(), args[0]);
271
+ if (key.isInvalid(args)) {
272
+ return;
273
+ }
274
+
275
+ NativeString collection(args.GetIsolate(), args[1]);
276
+ if (collection.isInvalid(args)) {
277
+ return;
278
+ }
279
+
280
+ kvStoreString[std::string(collection.getString())].erase(std::string(key.getString()));
281
+
282
+ //args.GetReturnValue().Set(Integer::New(args.GetIsolate(), value));
283
+ }
284
+
285
+ void uWS_deleteInteger(const FunctionCallbackInfo<Value> &args) {
286
+
287
+ NativeString key(args.GetIsolate(), args[0]);
288
+ if (key.isInvalid(args)) {
289
+ return;
290
+ }
291
+
292
+ NativeString collection(args.GetIsolate(), args[1]);
293
+ if (collection.isInvalid(args)) {
294
+ return;
295
+ }
296
+
297
+ kvStoreInteger[std::string(collection.getString())].erase(std::string(key.getString()));
298
+
299
+ //args.GetReturnValue().Set(Integer::New(args.GetIsolate(), value));
300
+ }
301
+
302
+ void uWS_deleteStringCollection(const FunctionCallbackInfo<Value> &args) {
303
+
304
+ NativeString collection(args.GetIsolate(), args[0]);
305
+ if (collection.isInvalid(args)) {
306
+ return;
307
+ }
308
+
309
+ kvStoreString.erase(std::string(collection.getString()));
310
+
311
+ //args.GetReturnValue().Set(integerKeys);
312
+ }
313
+
314
+ void uWS_deleteIntegerCollection(const FunctionCallbackInfo<Value> &args) {
315
+
316
+ NativeString collection(args.GetIsolate(), args[0]);
317
+ if (collection.isInvalid(args)) {
318
+ return;
319
+ }
320
+
321
+ kvStoreInteger.erase(std::string(collection.getString()));
322
+
323
+ //args.GetReturnValue().Set(integerKeys);
324
+ }
325
+
326
+ void uWS_lock(const FunctionCallbackInfo<Value> &args) {
327
+ kvMutex.lock();
328
+ }
329
+
330
+ void uWS_unlock(const FunctionCallbackInfo<Value> &args) {
331
+ kvMutex.unlock();
332
+ }
333
+
334
+ PerContextData *Main(Local<Object> exports) {
335
+
336
+ /* We pass isolate everywhere */
337
+ Isolate *isolate = exports->GetIsolate();
338
+
339
+ /* Init the template objects, SSL and non-SSL, store it in per context data */
340
+ PerContextData *perContextData = new PerContextData;
341
+ perContextData->isolate = isolate;
342
+ perContextData->reqTemplate[0].Reset(isolate, HttpRequestWrapper::init<false>(isolate));
343
+ perContextData->reqTemplate[1].Reset(isolate, HttpRequestWrapper::init<true>(isolate));
344
+ perContextData->resTemplate[0].Reset(isolate, HttpResponseWrapper::init<0>(isolate));
345
+ perContextData->resTemplate[1].Reset(isolate, HttpResponseWrapper::init<1>(isolate));
346
+ perContextData->resTemplate[2].Reset(isolate, HttpResponseWrapper::init<2>(isolate));
347
+ perContextData->wsTemplate[0].Reset(isolate, WebSocketWrapper::init<0>(isolate));
348
+ perContextData->wsTemplate[1].Reset(isolate, WebSocketWrapper::init<1>(isolate));
349
+
350
+ /* Refer to per context data via External */
351
+ Local<External> externalPerContextData = External::New(isolate, perContextData);
352
+
353
+ /* uWS namespace */
354
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "App", NewStringType::kNormal).ToLocalChecked(), FunctionTemplate::New(isolate, uWS_App<uWS::App>, externalPerContextData)->GetFunction(isolate->GetCurrentContext()).ToLocalChecked()).ToChecked();
355
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "SSLApp", NewStringType::kNormal).ToLocalChecked(), FunctionTemplate::New(isolate, uWS_App<uWS::SSLApp>, externalPerContextData)->GetFunction(isolate->GetCurrentContext()).ToLocalChecked()).ToChecked();
356
+
357
+ /* H3 experimental */
358
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "H3App", NewStringType::kNormal).ToLocalChecked(), FunctionTemplate::New(isolate, uWS_App<uWS::H3App>, externalPerContextData)->GetFunction(isolate->GetCurrentContext()).ToLocalChecked()).ToChecked();
359
+
360
+ /* Temporary KV store */
361
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "getString", NewStringType::kNormal).ToLocalChecked(), FunctionTemplate::New(isolate, uWS_getString)->GetFunction(isolate->GetCurrentContext()).ToLocalChecked()).ToChecked();
362
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "setString", NewStringType::kNormal).ToLocalChecked(), FunctionTemplate::New(isolate, uWS_setString)->GetFunction(isolate->GetCurrentContext()).ToLocalChecked()).ToChecked();
363
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "getInteger", NewStringType::kNormal).ToLocalChecked(), FunctionTemplate::New(isolate, uWS_getInteger)->GetFunction(isolate->GetCurrentContext()).ToLocalChecked()).ToChecked();
364
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "setInteger", NewStringType::kNormal).ToLocalChecked(), FunctionTemplate::New(isolate, uWS_setInteger)->GetFunction(isolate->GetCurrentContext()).ToLocalChecked()).ToChecked();
365
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "incInteger", NewStringType::kNormal).ToLocalChecked(), FunctionTemplate::New(isolate, uWS_incInteger)->GetFunction(isolate->GetCurrentContext()).ToLocalChecked()).ToChecked();
366
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "lock", NewStringType::kNormal).ToLocalChecked(), FunctionTemplate::New(isolate, uWS_lock)->GetFunction(isolate->GetCurrentContext()).ToLocalChecked()).ToChecked();
367
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "unlock", NewStringType::kNormal).ToLocalChecked(), FunctionTemplate::New(isolate, uWS_unlock)->GetFunction(isolate->GetCurrentContext()).ToLocalChecked()).ToChecked();
368
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "getIntegerKeys", NewStringType::kNormal).ToLocalChecked(), FunctionTemplate::New(isolate, uWS_getIntegerKeys)->GetFunction(isolate->GetCurrentContext()).ToLocalChecked()).ToChecked();
369
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "getStringKeys", NewStringType::kNormal).ToLocalChecked(), FunctionTemplate::New(isolate, uWS_getStringKeys)->GetFunction(isolate->GetCurrentContext()).ToLocalChecked()).ToChecked();
370
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "deleteString", NewStringType::kNormal).ToLocalChecked(), FunctionTemplate::New(isolate, uWS_deleteString)->GetFunction(isolate->GetCurrentContext()).ToLocalChecked()).ToChecked();
371
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "deleteInteger", NewStringType::kNormal).ToLocalChecked(), FunctionTemplate::New(isolate, uWS_deleteInteger)->GetFunction(isolate->GetCurrentContext()).ToLocalChecked()).ToChecked();
372
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "deleteStringCollection", NewStringType::kNormal).ToLocalChecked(), FunctionTemplate::New(isolate, uWS_deleteStringCollection)->GetFunction(isolate->GetCurrentContext()).ToLocalChecked()).ToChecked();
373
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "deleteIntegerCollection", NewStringType::kNormal).ToLocalChecked(), FunctionTemplate::New(isolate, uWS_deleteIntegerCollection)->GetFunction(isolate->GetCurrentContext()).ToLocalChecked()).ToChecked();
374
+
375
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "_cfg", NewStringType::kNormal).ToLocalChecked(), FunctionTemplate::New(isolate, uWS_cfg)->GetFunction(isolate->GetCurrentContext()).ToLocalChecked()).ToChecked();
376
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "getParts", NewStringType::kNormal).ToLocalChecked(), FunctionTemplate::New(isolate, uWS_getParts)->GetFunction(isolate->GetCurrentContext()).ToLocalChecked()).ToChecked();
377
+
378
+ /* Expose some µSockets functions directly under uWS namespace */
379
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "us_listen_socket_close", NewStringType::kNormal).ToLocalChecked(), FunctionTemplate::New(isolate, uWS_us_listen_socket_close)->GetFunction(isolate->GetCurrentContext()).ToLocalChecked()).ToChecked();
380
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "us_socket_local_port", NewStringType::kNormal).ToLocalChecked(), FunctionTemplate::New(isolate, uWS_us_socket_local_port)->GetFunction(isolate->GetCurrentContext()).ToLocalChecked()).ToChecked();
381
+
382
+ /* Compression enum */
383
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "DISABLED", NewStringType::kNormal).ToLocalChecked(), Integer::NewFromUnsigned(isolate, uWS::DISABLED)).ToChecked();
384
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "SHARED_COMPRESSOR", NewStringType::kNormal).ToLocalChecked(), Integer::NewFromUnsigned(isolate, uWS::SHARED_COMPRESSOR)).ToChecked();
385
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "SHARED_DECOMPRESSOR", NewStringType::kNormal).ToLocalChecked(), Integer::NewFromUnsigned(isolate, uWS::SHARED_DECOMPRESSOR)).ToChecked();
386
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "DEDICATED_DECOMPRESSOR", NewStringType::kNormal).ToLocalChecked(), Integer::NewFromUnsigned(isolate, uWS::DEDICATED_DECOMPRESSOR)).ToChecked();
387
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "DEDICATED_COMPRESSOR", NewStringType::kNormal).ToLocalChecked(), Integer::NewFromUnsigned(isolate, uWS::DEDICATED_COMPRESSOR)).ToChecked();
388
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "DEDICATED_COMPRESSOR_3KB", NewStringType::kNormal).ToLocalChecked(), Integer::NewFromUnsigned(isolate, uWS::DEDICATED_COMPRESSOR_3KB)).ToChecked();
389
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "DEDICATED_COMPRESSOR_4KB", NewStringType::kNormal).ToLocalChecked(), Integer::NewFromUnsigned(isolate, uWS::DEDICATED_COMPRESSOR_4KB)).ToChecked();
390
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "DEDICATED_COMPRESSOR_8KB", NewStringType::kNormal).ToLocalChecked(), Integer::NewFromUnsigned(isolate, uWS::DEDICATED_COMPRESSOR_8KB)).ToChecked();
391
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "DEDICATED_COMPRESSOR_16KB", NewStringType::kNormal).ToLocalChecked(), Integer::NewFromUnsigned(isolate, uWS::DEDICATED_COMPRESSOR_16KB)).ToChecked();
392
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "DEDICATED_COMPRESSOR_32KB", NewStringType::kNormal).ToLocalChecked(), Integer::NewFromUnsigned(isolate, uWS::DEDICATED_COMPRESSOR_32KB)).ToChecked();
393
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "DEDICATED_COMPRESSOR_64KB", NewStringType::kNormal).ToLocalChecked(), Integer::NewFromUnsigned(isolate, uWS::DEDICATED_COMPRESSOR_64KB)).ToChecked();
394
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "DEDICATED_COMPRESSOR_128KB", NewStringType::kNormal).ToLocalChecked(), Integer::NewFromUnsigned(isolate, uWS::DEDICATED_COMPRESSOR_128KB)).ToChecked();
395
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "DEDICATED_COMPRESSOR_256KB", NewStringType::kNormal).ToLocalChecked(), Integer::NewFromUnsigned(isolate, uWS::DEDICATED_COMPRESSOR_256KB)).ToChecked();
396
+
397
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "DEDICATED_DECOMPRESSOR_32KB", NewStringType::kNormal).ToLocalChecked(), Integer::NewFromUnsigned(isolate, uWS::DEDICATED_DECOMPRESSOR_32KB)).ToChecked();
398
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "DEDICATED_DECOMPRESSOR_16KB", NewStringType::kNormal).ToLocalChecked(), Integer::NewFromUnsigned(isolate, uWS::DEDICATED_DECOMPRESSOR_16KB)).ToChecked();
399
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "DEDICATED_DECOMPRESSOR_8KB", NewStringType::kNormal).ToLocalChecked(), Integer::NewFromUnsigned(isolate, uWS::DEDICATED_DECOMPRESSOR_8KB)).ToChecked();
400
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "DEDICATED_DECOMPRESSOR_4KB", NewStringType::kNormal).ToLocalChecked(), Integer::NewFromUnsigned(isolate, uWS::DEDICATED_DECOMPRESSOR_4KB)).ToChecked();
401
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "DEDICATED_DECOMPRESSOR_2KB", NewStringType::kNormal).ToLocalChecked(), Integer::NewFromUnsigned(isolate, uWS::DEDICATED_DECOMPRESSOR_2KB)).ToChecked();
402
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "DEDICATED_DECOMPRESSOR_1KB", NewStringType::kNormal).ToLocalChecked(), Integer::NewFromUnsigned(isolate, uWS::DEDICATED_DECOMPRESSOR_1KB)).ToChecked();
403
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "DEDICATED_DECOMPRESSOR_512B", NewStringType::kNormal).ToLocalChecked(), Integer::NewFromUnsigned(isolate, uWS::DEDICATED_DECOMPRESSOR_512B)).ToChecked();
404
+
405
+ /* Listen options */
406
+ exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "LIBUS_LISTEN_EXCLUSIVE_PORT", NewStringType::kNormal).ToLocalChecked(), Integer::NewFromUnsigned(isolate, LIBUS_LISTEN_EXCLUSIVE_PORT)).ToChecked();
407
+
408
+ return perContextData;
409
+ }
410
+
411
+ /* This is required when building as a Node.js addon */
412
+ #ifndef ADDON_IS_HOST
413
+ #include <node.h>
414
+ extern "C" NODE_MODULE_EXPORT void
415
+ NODE_MODULE_INITIALIZER(Local<Object> exports, Local<Value> module, Local<Context> context) {
416
+ /* Integrate uSockets with existing libuv loop */
417
+ uWS::Loop::get(node::GetCurrentEventLoop(context->GetIsolate()));
418
+ /* Register vanilla V8 addon */
419
+ PerContextData *perContextData = Main(exports);
420
+
421
+ /* We cannot rely on process.exit or process.beforeExit when it comes to WorkerThreads */
422
+ node::AddEnvironmentCleanupHook(context->GetIsolate(), [](void *arg) {
423
+
424
+ PerContextData *perContextData = (PerContextData *) arg;
425
+
426
+ /* Freeing apps here, it could be done earlier but not sooner */
427
+ perContextData->apps.clear();
428
+ perContextData->sslApps.clear();
429
+ /* Freeing the loop here means we give time for our timers to close, etc */
430
+ uWS::Loop::get()->free();
431
+
432
+ /* We can safely delete this since we no longer can call uWS.free */
433
+ delete perContextData;
434
+
435
+ }, perContextData);
436
+ }
437
+ #endif
package/src/host.cpp ADDED
@@ -0,0 +1,115 @@
1
+ /*
2
+ * Authored by Alex Hultman, 2018-2020.
3
+ * Intellectual property of third-party.
4
+
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ /* Welcome to the loopery host sources */
19
+ #include <libplatform/libplatform.h>
20
+ #include <v8.h>
21
+ using namespace v8;
22
+
23
+ #include <string>
24
+ #include <iostream>
25
+ #include <sstream>
26
+ #include <fstream>
27
+
28
+ #include "App.h"
29
+
30
+ // We load features from the addon
31
+ extern void Main(Local<Object> exports);
32
+
33
+ // console.log
34
+ void print(const FunctionCallbackInfo<Value> &args) {
35
+ String::Utf8Value utf8(args.GetIsolate(), args[0]);
36
+ std::cout << *utf8 << std::endl;
37
+ }
38
+
39
+ int main(int argc, char *argv[]) {
40
+
41
+ if (argc != 2) {
42
+ std::cout << "Usage: " << argv[0] << " <javascript source file>" << std::endl;
43
+ return 0;
44
+ }
45
+
46
+ // load script sources
47
+ std::ifstream t(argv[1]);
48
+ std::stringstream buffer;
49
+ buffer << t.rdbuf();
50
+ std::string code = buffer.str();
51
+
52
+ // inte den blekaste
53
+ V8::InitializeICUDefaultLocation(argv[0]);
54
+ V8::InitializeExternalStartupData(argv[0]);
55
+ std::unique_ptr<Platform> platform = platform::NewDefaultPlatform();
56
+ V8::InitializePlatform(platform.get());
57
+ V8::Initialize();
58
+
59
+ // isolate vet vi typ vad det är
60
+ Isolate::CreateParams create_params;
61
+ create_params.array_buffer_allocator = ArrayBuffer::Allocator::NewDefaultAllocator();
62
+ Isolate *isolate = Isolate::New(create_params);
63
+ {
64
+ Isolate::Scope isolate_scope(isolate);
65
+ HandleScope handle_scope(isolate);
66
+
67
+ // register functions (here is where addon.cpp comes in)
68
+ Local<ObjectTemplate> global = ObjectTemplate::New(isolate);
69
+
70
+ // add sign of stand-alone
71
+ global->Set(isolate, "runtime", String::NewFromUtf8(isolate, "µWebSockets.js", NewStringType::kNormal).ToLocalChecked());
72
+
73
+ // console namespace
74
+ Local<ObjectTemplate> console = ObjectTemplate::New(isolate);
75
+ // console.log
76
+ console->Set(String::NewFromUtf8(isolate, "log", NewStringType::kNormal).ToLocalChecked(),
77
+ FunctionTemplate::New(isolate, print));
78
+
79
+ // uWS namespace
80
+ Local<ObjectTemplate> uWS = ObjectTemplate::New(isolate);
81
+
82
+ global->Set(String::NewFromUtf8(isolate, "console", NewStringType::kNormal).ToLocalChecked(),
83
+ console);
84
+ global->Set(String::NewFromUtf8(isolate, "uWS", NewStringType::kNormal).ToLocalChecked(),
85
+ uWS);
86
+
87
+ // vi skapar ett context som håller det globala objektet
88
+ Local<Context> context = Context::New(isolate, nullptr, global);
89
+ Context::Scope context_scope(context);
90
+
91
+ // register µWS features under uWS namespace
92
+ Main(Local<Object>::Cast(context->Global()->Get(String::NewFromUtf8(isolate, "uWS", NewStringType::kNormal).ToLocalChecked())));
93
+
94
+ // ladda in scriptet (preprocessa include)
95
+ Local<String> source = String::NewFromUtf8(isolate, code.data(), NewStringType::kNormal, (int) code.length()).ToLocalChecked();
96
+
97
+ // kompilera hela skiten, med allt inläst
98
+ Local<Script> script = Script::Compile(context, source).ToLocalChecked();
99
+
100
+ // kör första "tick" där vi sätter upp saker
101
+ Local<Value> result = script->Run(context).ToLocalChecked();
102
+
103
+ // kör servern nu
104
+ uWS::Loop::defaultLoop()->run();
105
+ }
106
+
107
+
108
+ // fall through
109
+ std::cout << "Done, bye!" << std::endl;
110
+ isolate->Dispose();
111
+ V8::Dispose();
112
+ V8::ShutdownPlatform();
113
+ delete create_params.array_buffer_allocator;
114
+ return 0;
115
+ }
package/src/uws.js ADDED
@@ -0,0 +1,24 @@
1
+ /*
2
+ * Authored by Alex Hultman, 2018-2022.
3
+ * Intellectual property of third-party.
4
+
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ module.exports = (() => {
19
+ try {
20
+ return require('./uws_' + process.platform + '_' + process.arch + '_' + process.versions.modules + '.node');
21
+ } catch (e) {
22
+ throw new Error('This version of uWS.js supports only Node.js LTS versions 16, 18 and 20 on (glibc) Linux, macOS and Windows, on Tier 1 platforms (https://github.com/nodejs/node/blob/master/BUILDING.md#platform-list).\n\n' + e.toString());
23
+ }
24
+ })();
@@ -0,0 +1,102 @@
1
+ /* Test servers for autobahn, run with ASAN. /exit route shuts down everything */
2
+ const uWS = require('../dist/uws.js');
3
+
4
+ /* Keep track of all apps */
5
+ let apps = [];
6
+ let closing = false;
7
+
8
+ function listenWithSettings(settings) {
9
+ /* These are our shared SSL options */
10
+ let sslOptions = {
11
+ key_file_name: 'misc/key.pem',
12
+ cert_file_name: 'misc/cert.pem',
13
+ passphrase: '1234'
14
+ };
15
+
16
+ /* Create the app */
17
+ let app = settings.ssl ? uWS.SSLApp(sslOptions) : uWS.App(sslOptions);
18
+
19
+ /* Attach our behavior from settings */
20
+ app.ws('/*', {
21
+ compression: settings.compression,
22
+ maxPayloadLength: 16 * 1024 * 1024,
23
+ idleTimeout: 60,
24
+ maxBackpressure: 16 * 1024 * 1204,
25
+ open: (ws, req) => {
26
+ if (settings.pubsub) {
27
+ ws.subscribe('broadcast');
28
+ }
29
+ },
30
+ message: (ws, message, isBinary) => {
31
+ if (settings.pubsub) {
32
+ ws.publish('broadcast', message, isBinary);
33
+ } else {
34
+ ws.send(message, isBinary, true);
35
+ }
36
+ }
37
+ }).any('/exit', (res, req) => {
38
+ /* Shut down everything on this route */
39
+ if (!closing) {
40
+ apps.forEach((a) => {
41
+ uWS.us_listen_socket_close(a.listenSocket);
42
+ });
43
+ closing = true;
44
+ }
45
+
46
+ /* Close this connection */
47
+ res.close();
48
+ }).listen(settings.port, (listenSocket) => {
49
+ if (listenSocket) {
50
+ /* Add this app with its listenSocket */
51
+ apps.push({
52
+ app: app,
53
+ listenSocket: listenSocket
54
+ });
55
+ console.log('Up and running: ' + JSON.stringify(settings));
56
+ } else {
57
+ /* Failure here */
58
+ console.log('Failed to listen, closing everything now');
59
+ process.exit(0);
60
+ }
61
+ });
62
+ }
63
+
64
+ /* non-SSL, non-compression */
65
+ listenWithSettings({
66
+ port: 9001,
67
+ ssl: false,
68
+ compression: uWS.DISABLED,
69
+ pubsub: false
70
+ });
71
+
72
+ /* SSL, shared compressor */
73
+ listenWithSettings({
74
+ port: 9002,
75
+ ssl: true,
76
+ compression: uWS.SHARED_COMPRESSOR,
77
+ pubsub: false
78
+ });
79
+
80
+ /* non-SSL, dedicated compressor */
81
+ listenWithSettings({
82
+ port: 9003,
83
+ ssl: false,
84
+ compression: uWS.DEDICATED_COMPRESSOR,
85
+ pubsub: false
86
+ });
87
+
88
+ /* pub/sub based, non-SSL, non-compression */
89
+ listenWithSettings({
90
+ port: 9004,
91
+ ssl: false,
92
+ compression: uWS.DISABLED,
93
+ pubsub: true
94
+ });
95
+
96
+ /* pub/sub based, SSL, non-compression */
97
+ listenWithSettings({
98
+ port: 9005,
99
+ ssl: true,
100
+ compression: uWS.DISABLED,
101
+ pubsub: true
102
+ });