uwebsockets 2.0.0 → 2.2.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 +8 -4
- 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/tests/Hammer.js
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/* Welcome to the so called hammer test, or if you want, moron test.
|
|
2
|
+
* Here we test hammering the library in all kinds of crazy ways.
|
|
3
|
+
* Establish connections, have them perform random operations so to
|
|
4
|
+
* randomly explore the entire state space while performing random
|
|
5
|
+
* operations to test strange edge cases. */
|
|
6
|
+
|
|
7
|
+
/* Run with AddressSanitizer enabled for best effect. */
|
|
8
|
+
|
|
9
|
+
/* We use websockets/ws as client counterpart */
|
|
10
|
+
const WebSocket = require('ws');
|
|
11
|
+
|
|
12
|
+
const uWS = require('../dist/uws.js');
|
|
13
|
+
const port = 9001;
|
|
14
|
+
|
|
15
|
+
let openedClientConnections = 0;
|
|
16
|
+
let closedClientConnections = 0;
|
|
17
|
+
|
|
18
|
+
let listenSocket;
|
|
19
|
+
|
|
20
|
+
const maxBackpressure = 50 * 1024 * 1024;
|
|
21
|
+
const maxPayloadSize = 5 * 1024 * 1024;
|
|
22
|
+
const largeBuffer = new ArrayBuffer(maxPayloadSize);
|
|
23
|
+
|
|
24
|
+
function printStatistics() {
|
|
25
|
+
console.log('Opened clients ' + openedClientConnections);
|
|
26
|
+
console.log('Closed clients ' + closedClientConnections + '\n');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/* 0 to 1-less than max */
|
|
30
|
+
function getRandomInt(max) {
|
|
31
|
+
return Math.floor(Math.random() * Math.floor(max));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/* This gets called every time we either open a new connection,
|
|
35
|
+
* or it immediately land in websockets/ws error handler */
|
|
36
|
+
function accountForConnection() {
|
|
37
|
+
/* Open more connections */
|
|
38
|
+
if (++openedClientConnections < /*100*/ 1000) {
|
|
39
|
+
establishNewConnection();
|
|
40
|
+
} else {
|
|
41
|
+
/* Stop listening */
|
|
42
|
+
uWS.us_listen_socket_close(listenSocket);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function establishNewConnection() {
|
|
47
|
+
const ws = new WebSocket('ws://localhost:' + port);
|
|
48
|
+
|
|
49
|
+
ws.on('open', () => {
|
|
50
|
+
/* Mark this socket as opened */
|
|
51
|
+
ws._opened = true;
|
|
52
|
+
accountForConnection();
|
|
53
|
+
|
|
54
|
+
printStatistics();
|
|
55
|
+
performRandomClientAction(ws);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
/* It seems you can get messages after close?! */
|
|
59
|
+
ws.on('message', (data) => {
|
|
60
|
+
performRandomClientAction(ws);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
/* Close can be called more times than open, websockets/ws is really messy! */
|
|
64
|
+
ws.on('close', () => {
|
|
65
|
+
/* Check if this websocket really was opened first */
|
|
66
|
+
if (!ws._opened) {
|
|
67
|
+
accountForConnection();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
closedClientConnections++;
|
|
71
|
+
printStatistics();
|
|
72
|
+
/* I guess there is no need for us to call anything
|
|
73
|
+
* here, websockets/ws will not send anything to us anyways */
|
|
74
|
+
//performRandomClientAction(ws);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
ws.on('error', () => {
|
|
78
|
+
/* We simply ignore errors. websockets/ws will call our close handler
|
|
79
|
+
* on errors, potentially before even calling the open handler */
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/* Perform random websockets/ws action */
|
|
84
|
+
function performRandomClientAction(ws) {
|
|
85
|
+
/* 0, 1, 2 but never 3 */
|
|
86
|
+
let action = getRandomInt(3);
|
|
87
|
+
|
|
88
|
+
/* Sending a message should have higher probability */
|
|
89
|
+
if (getRandomInt(100) < 80) {
|
|
90
|
+
action = 1;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
switch (action) {
|
|
94
|
+
case 0: {
|
|
95
|
+
ws.close();
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
case 1: {
|
|
99
|
+
/* Length should be random from small to huge */
|
|
100
|
+
try {
|
|
101
|
+
ws.send('a test message');
|
|
102
|
+
} catch (e) {
|
|
103
|
+
/* Apparently websockets/ws can throw at any moment */
|
|
104
|
+
|
|
105
|
+
}
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
case 2: {
|
|
109
|
+
ws.terminate();
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/* Perform random uWebSockets.js action */
|
|
116
|
+
function performRandomServerAction(ws, uniform) {
|
|
117
|
+
/* 0, 1, 2 but never 3 */
|
|
118
|
+
let action = getRandomInt(3);
|
|
119
|
+
|
|
120
|
+
/* Sending a message should have higher probability,
|
|
121
|
+
* except for when we are draining. */
|
|
122
|
+
if (!uniform) {
|
|
123
|
+
if (getRandomInt(100) < 80) {
|
|
124
|
+
action = 1;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
switch (action) {
|
|
129
|
+
case 0: {
|
|
130
|
+
ws.end();
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
case 1: {
|
|
134
|
+
/* If we have very high backpressure we skip sending more */
|
|
135
|
+
if (ws.getBufferedAmount() > maxBackpressure) {
|
|
136
|
+
/* Do something else instead */
|
|
137
|
+
performRandomServerAction(ws);
|
|
138
|
+
} else {
|
|
139
|
+
/* Length should be random from small to huge, ArrayBuffer.slice is a copy (bad but we don't care I guess) */
|
|
140
|
+
ws.send(largeBuffer.slice(0, getRandomInt(maxPayloadSize + 1)));
|
|
141
|
+
}
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
case 2: {
|
|
145
|
+
ws.close();
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const app = uWS./*SSL*/App({
|
|
152
|
+
key_file_name: 'misc/key.pem',
|
|
153
|
+
cert_file_name: 'misc/cert.pem',
|
|
154
|
+
passphrase: '1234'
|
|
155
|
+
}).ws('/*', {
|
|
156
|
+
compression: 0,
|
|
157
|
+
/* We intentionally accept less than what might be sent so to test force closing */
|
|
158
|
+
maxPayloadLength: maxPayloadSize / 2,
|
|
159
|
+
idleTimeout: 100,
|
|
160
|
+
|
|
161
|
+
open: (ws, req) => {
|
|
162
|
+
/* Doing a terminate here will be interesting */
|
|
163
|
+
performRandomServerAction(ws, false);
|
|
164
|
+
},
|
|
165
|
+
message: (ws, message, isBinary) => {
|
|
166
|
+
performRandomServerAction(ws, false);
|
|
167
|
+
},
|
|
168
|
+
drain: (ws) => {
|
|
169
|
+
/* We only perform actions while draining rarely (5%), and we do it uniformly.
|
|
170
|
+
* There's no real NEED to do anything here, as it will eventually result in
|
|
171
|
+
* message event for client. */
|
|
172
|
+
if (getRandomInt(100) < 5) {
|
|
173
|
+
performRandomServerAction(ws, true);
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
close: (ws, code, message) => {
|
|
177
|
+
/* TODO: We SHOULD TECHNICALLY allow sending here.
|
|
178
|
+
* It should not throw, but just silently ignore it
|
|
179
|
+
* as it makes no sense to send on a closed socket
|
|
180
|
+
* while still being technically valid */
|
|
181
|
+
try {
|
|
182
|
+
performRandomServerAction(ws, false);
|
|
183
|
+
} catch (e) {
|
|
184
|
+
/* We expect to land here always, since socket is invalid */
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
/* We should never land here */
|
|
188
|
+
uWS.print('ERROR: Did not throw in close!');
|
|
189
|
+
process.exit(-1);
|
|
190
|
+
}
|
|
191
|
+
}).any('/*', (res, req) => {
|
|
192
|
+
res.end('Nothing to see here!');
|
|
193
|
+
}).listen(port, (token) => {
|
|
194
|
+
if (token) {
|
|
195
|
+
console.log('Hammering on port ' + port);
|
|
196
|
+
|
|
197
|
+
/* Establish first connection */
|
|
198
|
+
establishNewConnection();
|
|
199
|
+
|
|
200
|
+
/* Use this to stop listening when done */
|
|
201
|
+
listenSocket = token;
|
|
202
|
+
}
|
|
203
|
+
});
|
package/tests/Makefile
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"outdir": "./reports/servers",
|
|
3
|
+
"servers": [
|
|
4
|
+
{
|
|
5
|
+
"url": "ws://localhost:9001",
|
|
6
|
+
"agent": "uWebSockets.js non-SSL, non-compression"
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"url": "wss://localhost:9002",
|
|
10
|
+
"agent": "uWebSockets.js SSL, shared compressor"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"url": "ws://localhost:9003",
|
|
14
|
+
"agent": "uWebSockets.js non-SSL, dedicated compressor"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"url": "ws://localhost:9004",
|
|
18
|
+
"agent": "uWebSockets.js non-SSL, non-compression, pubsub based"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"url": "wss://localhost:9005",
|
|
22
|
+
"agent": "uWebSockets.js SSL, non-compression, pubsub based"
|
|
23
|
+
}
|
|
24
|
+
],
|
|
25
|
+
"cases": ["*.*"],
|
|
26
|
+
"exclude-cases": [],
|
|
27
|
+
"exclude-agent-cases": {}
|
|
28
|
+
}
|