1'use strict'; 2const common = require('../common'); 3if (!common.hasCrypto) 4 common.skip('missing crypto'); 5 6const assert = require('assert'); 7const http2 = require('http2'); 8const net = require('net'); 9 10// Verify that creating a number of invalid HTTP/2 streams will 11// result in the peer closing the session within maxSessionInvalidFrames 12// frames. 13 14const maxSessionInvalidFrames = 100; 15const server = http2.createServer({ maxSessionInvalidFrames }); 16server.on('stream', (stream) => { 17 stream.respond({ 18 'content-type': 'text/plain', 19 ':status': 200 20 }); 21 stream.end('Hello, world!\n'); 22}); 23 24server.listen(0, () => { 25 const h2header = Buffer.alloc(9); 26 const conn = net.connect(server.address().port); 27 28 conn.write('PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n'); 29 30 h2header[3] = 4; // Send a settings frame. 31 conn.write(Buffer.from(h2header)); 32 33 let inbuf = Buffer.alloc(0); 34 let state = 'settingsHeader'; 35 let settingsFrameLength; 36 conn.on('data', (chunk) => { 37 inbuf = Buffer.concat([inbuf, chunk]); 38 switch (state) { 39 case 'settingsHeader': 40 if (inbuf.length < 9) return; 41 settingsFrameLength = inbuf.readIntBE(0, 3); 42 inbuf = inbuf.slice(9); 43 state = 'readingSettings'; 44 // Fallthrough 45 case 'readingSettings': 46 if (inbuf.length < settingsFrameLength) return; 47 inbuf = inbuf.slice(settingsFrameLength); 48 h2header[3] = 4; // Send a settings ACK. 49 h2header[4] = 1; 50 conn.write(Buffer.from(h2header)); 51 state = 'ignoreInput'; 52 writeRequests(); 53 } 54 }); 55 56 let gotError = false; 57 let streamId = 1; 58 let reqCount = 0; 59 60 function writeRequests() { 61 for (let i = 1; i < 10 && !gotError; i++) { 62 h2header[3] = 1; // HEADERS 63 h2header[4] = 0x5; // END_HEADERS|END_STREAM 64 h2header.writeIntBE(1, 0, 3); // Length: 1 65 h2header.writeIntBE(streamId, 5, 4); // Stream ID 66 streamId += 2; 67 // 0x88 = :status: 200 68 if (!conn.write(Buffer.concat([h2header, Buffer.from([0x88])]))) { 69 break; 70 } 71 reqCount++; 72 } 73 // Timeout requests to slow down the rate so we get more accurate reqCount. 74 if (!gotError) 75 setTimeout(writeRequests, 10); 76 } 77 78 conn.once('error', common.mustCall(() => { 79 gotError = true; 80 assert.ok(Math.abs(reqCount - maxSessionInvalidFrames) < 100, 81 `Request count (${reqCount}) must be around (±100)` + 82 ` maxSessionInvalidFrames option (${maxSessionInvalidFrames})`); 83 conn.destroy(); 84 server.close(); 85 })); 86}); 87