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({ 27 port: server.address().port, 28 allowHalfOpen: true 29 }); 30 31 conn.write('PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n'); 32 33 h2header[3] = 4; // Send a settings frame. 34 conn.write(Buffer.from(h2header)); 35 36 let inbuf = Buffer.alloc(0); 37 let state = 'settingsHeader'; 38 let settingsFrameLength; 39 conn.on('data', (chunk) => { 40 inbuf = Buffer.concat([inbuf, chunk]); 41 switch (state) { 42 case 'settingsHeader': 43 if (inbuf.length < 9) return; 44 settingsFrameLength = inbuf.readIntBE(0, 3); 45 inbuf = inbuf.slice(9); 46 state = 'readingSettings'; 47 // Fallthrough 48 case 'readingSettings': 49 if (inbuf.length < settingsFrameLength) return; 50 inbuf = inbuf.slice(settingsFrameLength); 51 h2header[3] = 4; // Send a settings ACK. 52 h2header[4] = 1; 53 conn.write(Buffer.from(h2header)); 54 state = 'ignoreInput'; 55 writeRequests(); 56 } 57 }); 58 59 let gotError = false; 60 let streamId = 1; 61 let reqCount = 0; 62 63 function writeRequests() { 64 for (let i = 1; i < 10 && !gotError; i++) { 65 h2header[3] = 1; // HEADERS 66 h2header[4] = 0x5; // END_HEADERS|END_STREAM 67 h2header.writeIntBE(1, 0, 3); // Length: 1 68 h2header.writeIntBE(streamId, 5, 4); // Stream ID 69 streamId += 2; 70 // 0x88 = :status: 200 71 if (!conn.write(Buffer.concat([h2header, Buffer.from([0x88])]))) { 72 break; 73 } 74 reqCount++; 75 } 76 // Timeout requests to slow down the rate so we get more accurate reqCount. 77 if (!gotError) 78 setTimeout(writeRequests, 10); 79 } 80 81 conn.once('error', common.mustCall(() => { 82 gotError = true; 83 assert.ok(Math.abs(reqCount - maxSessionInvalidFrames) < 100, 84 `Request count (${reqCount}) must be around (±100)` + 85 ` maxSessionInvalidFrames option (${maxSessionInvalidFrames})`); 86 conn.destroy(); 87 server.close(); 88 })); 89}); 90