'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({ port: server.address().port, allowHalfOpen: true }); 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(); })); });