summaryrefslogtreecommitdiff
path: root/test/parallel/test-http2-max-invalid-frames.js
diff options
context:
space:
mode:
Diffstat (limited to 'test/parallel/test-http2-max-invalid-frames.js')
-rw-r--r--test/parallel/test-http2-max-invalid-frames.js86
1 files changed, 86 insertions, 0 deletions
diff --git a/test/parallel/test-http2-max-invalid-frames.js b/test/parallel/test-http2-max-invalid-frames.js
new file mode 100644
index 0000000000..597bd8e811
--- /dev/null
+++ b/test/parallel/test-http2-max-invalid-frames.js
@@ -0,0 +1,86 @@
+'use strict';
+const common = require('../common');
+if (!common.hasCrypto)
+ common.skip('missing crypto');
+
+const assert = require('assert');
+const http2 = require('http2');
+const net = require('net');
+
+// Verify that creating a number of invalid HTTP/2 streams will
+// result in the peer closing the session within maxSessionInvalidFrames
+// frames.
+
+const maxSessionInvalidFrames = 100;
+const server = http2.createServer({ maxSessionInvalidFrames });
+server.on('stream', (stream) => {
+ stream.respond({
+ 'content-type': 'text/plain',
+ ':status': 200
+ });
+ stream.end('Hello, world!\n');
+});
+
+server.listen(0, () => {
+ const h2header = Buffer.alloc(9);
+ const conn = net.connect(server.address().port);
+
+ conn.write('PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n');
+
+ h2header[3] = 4; // Send a settings frame.
+ conn.write(Buffer.from(h2header));
+
+ let inbuf = Buffer.alloc(0);
+ let state = 'settingsHeader';
+ let settingsFrameLength;
+ conn.on('data', (chunk) => {
+ inbuf = Buffer.concat([inbuf, chunk]);
+ switch (state) {
+ case 'settingsHeader':
+ if (inbuf.length < 9) return;
+ settingsFrameLength = inbuf.readIntBE(0, 3);
+ inbuf = inbuf.slice(9);
+ state = 'readingSettings';
+ // Fallthrough
+ case 'readingSettings':
+ if (inbuf.length < settingsFrameLength) return;
+ inbuf = inbuf.slice(settingsFrameLength);
+ h2header[3] = 4; // Send a settings ACK.
+ h2header[4] = 1;
+ conn.write(Buffer.from(h2header));
+ state = 'ignoreInput';
+ writeRequests();
+ }
+ });
+
+ let gotError = false;
+ let streamId = 1;
+ let reqCount = 0;
+
+ function writeRequests() {
+ for (let i = 1; i < 10 && !gotError; i++) {
+ h2header[3] = 1; // HEADERS
+ h2header[4] = 0x5; // END_HEADERS|END_STREAM
+ h2header.writeIntBE(1, 0, 3); // Length: 1
+ h2header.writeIntBE(streamId, 5, 4); // Stream ID
+ streamId += 2;
+ // 0x88 = :status: 200
+ if (!conn.write(Buffer.concat([h2header, Buffer.from([0x88])]))) {
+ break;
+ }
+ reqCount++;
+ }
+ // Timeout requests to slow down the rate so we get more accurate reqCount.
+ if (!gotError)
+ setTimeout(writeRequests, 10);
+ }
+
+ conn.once('error', common.mustCall(() => {
+ gotError = true;
+ assert.ok(Math.abs(reqCount - maxSessionInvalidFrames) < 100,
+ `Request count (${reqCount}) must be around (±100)` +
+ ` maxSessionInvalidFrames option (${maxSessionInvalidFrames})`);
+ conn.destroy();
+ server.close();
+ }));
+});