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.
- package/Makefile +11 -0
- package/README.md +38 -44
- package/build.c +185 -0
- package/docs/Makefile +2 -0
- package/docs/generated/.nojekyll +1 -0
- package/docs/generated/assets/highlight.css +22 -0
- package/docs/generated/assets/main.js +4 -0
- package/docs/generated/assets/search.js +1 -0
- package/docs/generated/assets/style.css +1280 -0
- package/docs/generated/enums/ListenOptions.html +70 -0
- package/docs/generated/functions/App.html +94 -0
- package/docs/generated/functions/SSLApp.html +93 -0
- package/docs/generated/functions/getParts.html +95 -0
- package/docs/generated/functions/us_listen_socket_close.html +93 -0
- package/docs/generated/functions/us_socket_local_port.html +93 -0
- package/docs/generated/index.html +131 -0
- package/docs/generated/interfaces/AppOptions.html +115 -0
- package/docs/generated/interfaces/HttpRequest.html +204 -0
- package/docs/generated/interfaces/HttpResponse.html +400 -0
- package/docs/generated/interfaces/MultipartField.html +88 -0
- package/docs/generated/interfaces/TemplatedApp.html +595 -0
- package/docs/generated/interfaces/WebSocket.html +303 -0
- package/docs/generated/interfaces/WebSocketBehavior.html +331 -0
- package/docs/generated/interfaces/us_listen_socket.html +89 -0
- package/docs/generated/interfaces/us_socket.html +89 -0
- package/docs/generated/interfaces/us_socket_context_t.html +89 -0
- package/docs/generated/types/CompressOptions.html +84 -0
- package/docs/generated/types/RecognizedString.html +89 -0
- package/docs/generated/variables/DEDICATED_COMPRESSOR_128KB.html +84 -0
- package/docs/generated/variables/DEDICATED_COMPRESSOR_16KB.html +84 -0
- package/docs/generated/variables/DEDICATED_COMPRESSOR_256KB.html +84 -0
- package/docs/generated/variables/DEDICATED_COMPRESSOR_32KB.html +84 -0
- package/docs/generated/variables/DEDICATED_COMPRESSOR_3KB.html +84 -0
- package/docs/generated/variables/DEDICATED_COMPRESSOR_4KB.html +84 -0
- package/docs/generated/variables/DEDICATED_COMPRESSOR_64KB.html +84 -0
- package/docs/generated/variables/DEDICATED_COMPRESSOR_8KB.html +84 -0
- package/docs/generated/variables/DEDICATED_DECOMPRESSOR.html +84 -0
- package/docs/generated/variables/DEDICATED_DECOMPRESSOR_16KB.html +84 -0
- package/docs/generated/variables/DEDICATED_DECOMPRESSOR_1KB.html +84 -0
- package/docs/generated/variables/DEDICATED_DECOMPRESSOR_2KB.html +84 -0
- package/docs/generated/variables/DEDICATED_DECOMPRESSOR_32KB.html +84 -0
- package/docs/generated/variables/DEDICATED_DECOMPRESSOR_4KB.html +84 -0
- package/docs/generated/variables/DEDICATED_DECOMPRESSOR_512B.html +84 -0
- package/docs/generated/variables/DEDICATED_DECOMPRESSOR_8KB.html +84 -0
- package/docs/generated/variables/DISABLED.html +84 -0
- package/docs/generated/variables/SHARED_COMPRESSOR.html +84 -0
- package/docs/generated/variables/SHARED_DECOMPRESSOR.html +84 -0
- package/docs/index.d.ts +395 -0
- package/docs/report.pdf +0 -0
- package/docs/tsconfig.json +11 -0
- package/examples/AsyncFunction.js +43 -0
- package/examples/AutomaticPortSelection.js +20 -0
- package/examples/Backpressure.js +75 -0
- package/examples/Broadcast.js +39 -0
- package/examples/GracefulShutdown.js +39 -0
- package/examples/H3lloWorld.js +23 -0
- package/examples/Headers.js +31 -0
- package/examples/HelloWorld.js +18 -0
- package/examples/JsonPost.js +72 -0
- package/examples/ProxyProtocol.js +25 -0
- package/examples/PubSub.js +57 -0
- package/examples/RateLimit.js +69 -0
- package/examples/Router.js +30 -0
- package/examples/ServerName.js +34 -0
- package/examples/ServerSentEvents.js +48 -0
- package/examples/SlowReceiver.js +53 -0
- package/examples/Upgrade.js +51 -0
- package/examples/UpgradeAsync.js +80 -0
- package/examples/Upload.js +36 -0
- package/examples/VideoStreamer.js +115 -0
- package/examples/VideoStreamerSync.js +42 -0
- package/examples/WebSockets.js +37 -0
- package/examples/WorkerThreads.js +33 -0
- package/misc/Manycast latency comparison [lower is better].png +0 -0
- package/misc/addon.pro +24 -0
- package/misc/cert.pem +21 -0
- package/misc/chart.png +0 -0
- package/misc/features_strip.png +0 -0
- package/misc/host.pro +31 -0
- package/misc/key.pem +28 -0
- package/misc/logo.svg +1 -0
- package/misc/streaming.png +0 -0
- package/package.json +1 -1
- package/src/AppWrapper.h +734 -0
- package/src/HttpRequestWrapper.h +196 -0
- package/src/HttpResponseWrapper.h +463 -0
- package/src/Utilities.h +172 -0
- package/src/WebSocketWrapper.h +348 -0
- package/src/addon.cpp +437 -0
- package/src/host.cpp +115 -0
- package/src/uws.js +24 -0
- package/tests/Autobahn.js +102 -0
- package/tests/Hammer.js +203 -0
- package/tests/Makefile +2 -0
- 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
|
+
});
|