11cb0ef41Sopenharmony_ci'use strict'; 21cb0ef41Sopenharmony_ciconst common = require('../common'); 31cb0ef41Sopenharmony_ciif (!common.hasCrypto) 41cb0ef41Sopenharmony_ci common.skip('missing crypto'); 51cb0ef41Sopenharmony_ci 61cb0ef41Sopenharmony_ciconst assert = require('assert'); 71cb0ef41Sopenharmony_ciconst http2 = require('http2'); 81cb0ef41Sopenharmony_ciconst net = require('net'); 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ci// Verify that creating a number of invalid HTTP/2 streams will 111cb0ef41Sopenharmony_ci// result in the peer closing the session within maxSessionInvalidFrames 121cb0ef41Sopenharmony_ci// frames. 131cb0ef41Sopenharmony_ci 141cb0ef41Sopenharmony_ciconst maxSessionInvalidFrames = 100; 151cb0ef41Sopenharmony_ciconst server = http2.createServer({ maxSessionInvalidFrames }); 161cb0ef41Sopenharmony_ciserver.on('stream', (stream) => { 171cb0ef41Sopenharmony_ci stream.respond({ 181cb0ef41Sopenharmony_ci 'content-type': 'text/plain', 191cb0ef41Sopenharmony_ci ':status': 200 201cb0ef41Sopenharmony_ci }); 211cb0ef41Sopenharmony_ci stream.end('Hello, world!\n'); 221cb0ef41Sopenharmony_ci}); 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_ciserver.listen(0, () => { 251cb0ef41Sopenharmony_ci const h2header = Buffer.alloc(9); 261cb0ef41Sopenharmony_ci const conn = net.connect({ 271cb0ef41Sopenharmony_ci port: server.address().port, 281cb0ef41Sopenharmony_ci allowHalfOpen: true 291cb0ef41Sopenharmony_ci }); 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_ci conn.write('PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n'); 321cb0ef41Sopenharmony_ci 331cb0ef41Sopenharmony_ci h2header[3] = 4; // Send a settings frame. 341cb0ef41Sopenharmony_ci conn.write(Buffer.from(h2header)); 351cb0ef41Sopenharmony_ci 361cb0ef41Sopenharmony_ci let inbuf = Buffer.alloc(0); 371cb0ef41Sopenharmony_ci let state = 'settingsHeader'; 381cb0ef41Sopenharmony_ci let settingsFrameLength; 391cb0ef41Sopenharmony_ci conn.on('data', (chunk) => { 401cb0ef41Sopenharmony_ci inbuf = Buffer.concat([inbuf, chunk]); 411cb0ef41Sopenharmony_ci switch (state) { 421cb0ef41Sopenharmony_ci case 'settingsHeader': 431cb0ef41Sopenharmony_ci if (inbuf.length < 9) return; 441cb0ef41Sopenharmony_ci settingsFrameLength = inbuf.readIntBE(0, 3); 451cb0ef41Sopenharmony_ci inbuf = inbuf.slice(9); 461cb0ef41Sopenharmony_ci state = 'readingSettings'; 471cb0ef41Sopenharmony_ci // Fallthrough 481cb0ef41Sopenharmony_ci case 'readingSettings': 491cb0ef41Sopenharmony_ci if (inbuf.length < settingsFrameLength) return; 501cb0ef41Sopenharmony_ci inbuf = inbuf.slice(settingsFrameLength); 511cb0ef41Sopenharmony_ci h2header[3] = 4; // Send a settings ACK. 521cb0ef41Sopenharmony_ci h2header[4] = 1; 531cb0ef41Sopenharmony_ci conn.write(Buffer.from(h2header)); 541cb0ef41Sopenharmony_ci state = 'ignoreInput'; 551cb0ef41Sopenharmony_ci writeRequests(); 561cb0ef41Sopenharmony_ci } 571cb0ef41Sopenharmony_ci }); 581cb0ef41Sopenharmony_ci 591cb0ef41Sopenharmony_ci let gotError = false; 601cb0ef41Sopenharmony_ci let streamId = 1; 611cb0ef41Sopenharmony_ci let reqCount = 0; 621cb0ef41Sopenharmony_ci 631cb0ef41Sopenharmony_ci function writeRequests() { 641cb0ef41Sopenharmony_ci for (let i = 1; i < 10 && !gotError; i++) { 651cb0ef41Sopenharmony_ci h2header[3] = 1; // HEADERS 661cb0ef41Sopenharmony_ci h2header[4] = 0x5; // END_HEADERS|END_STREAM 671cb0ef41Sopenharmony_ci h2header.writeIntBE(1, 0, 3); // Length: 1 681cb0ef41Sopenharmony_ci h2header.writeIntBE(streamId, 5, 4); // Stream ID 691cb0ef41Sopenharmony_ci streamId += 2; 701cb0ef41Sopenharmony_ci // 0x88 = :status: 200 711cb0ef41Sopenharmony_ci if (!conn.write(Buffer.concat([h2header, Buffer.from([0x88])]))) { 721cb0ef41Sopenharmony_ci break; 731cb0ef41Sopenharmony_ci } 741cb0ef41Sopenharmony_ci reqCount++; 751cb0ef41Sopenharmony_ci } 761cb0ef41Sopenharmony_ci // Timeout requests to slow down the rate so we get more accurate reqCount. 771cb0ef41Sopenharmony_ci if (!gotError) 781cb0ef41Sopenharmony_ci setTimeout(writeRequests, 10); 791cb0ef41Sopenharmony_ci } 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ci conn.once('error', common.mustCall(() => { 821cb0ef41Sopenharmony_ci gotError = true; 831cb0ef41Sopenharmony_ci assert.ok(Math.abs(reqCount - maxSessionInvalidFrames) < 100, 841cb0ef41Sopenharmony_ci `Request count (${reqCount}) must be around (±100)` + 851cb0ef41Sopenharmony_ci ` maxSessionInvalidFrames option (${maxSessionInvalidFrames})`); 861cb0ef41Sopenharmony_ci conn.destroy(); 871cb0ef41Sopenharmony_ci server.close(); 881cb0ef41Sopenharmony_ci })); 891cb0ef41Sopenharmony_ci}); 90