11cb0ef41Sopenharmony_ci'use strict'; 21cb0ef41Sopenharmony_ci// Flags: --expose-internals 31cb0ef41Sopenharmony_ci 41cb0ef41Sopenharmony_ciconst common = require('../common'); 51cb0ef41Sopenharmony_ciconst assert = require('assert'); 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ciif (!common.hasCrypto) 81cb0ef41Sopenharmony_ci common.skip('missing crypto'); 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ciconst h2 = require('http2'); 111cb0ef41Sopenharmony_ciconst net = require('net'); 121cb0ef41Sopenharmony_ciconst { NghttpError } = require('internal/http2/util'); 131cb0ef41Sopenharmony_ciconst h2test = require('../common/http2'); 141cb0ef41Sopenharmony_cilet client; 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_ciconst server = h2.createServer(); 171cb0ef41Sopenharmony_cilet gotFirstStreamId1; 181cb0ef41Sopenharmony_ciserver.on('stream', common.mustCall((stream) => { 191cb0ef41Sopenharmony_ci stream.respond(); 201cb0ef41Sopenharmony_ci stream.end('ok'); 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_ci // Http2Server should be fast enough to respond to and close 231cb0ef41Sopenharmony_ci // the first streams with ID 1 and ID 3 without errors. 241cb0ef41Sopenharmony_ci 251cb0ef41Sopenharmony_ci // Test for errors in 'close' event to ensure no errors on some streams. 261cb0ef41Sopenharmony_ci stream.on('error', () => {}); 271cb0ef41Sopenharmony_ci stream.on('close', (err) => { 281cb0ef41Sopenharmony_ci if (stream.id === 1) { 291cb0ef41Sopenharmony_ci if (gotFirstStreamId1) { 301cb0ef41Sopenharmony_ci // We expect our outgoing frames to fail on Stream ID 1 the second time 311cb0ef41Sopenharmony_ci // because a stream with ID 1 was already closed before. 321cb0ef41Sopenharmony_ci common.expectsError({ 331cb0ef41Sopenharmony_ci constructor: NghttpError, 341cb0ef41Sopenharmony_ci code: 'ERR_HTTP2_ERROR', 351cb0ef41Sopenharmony_ci message: 'Stream was already closed or invalid' 361cb0ef41Sopenharmony_ci }); 371cb0ef41Sopenharmony_ci return; 381cb0ef41Sopenharmony_ci } 391cb0ef41Sopenharmony_ci gotFirstStreamId1 = true; 401cb0ef41Sopenharmony_ci } 411cb0ef41Sopenharmony_ci assert.strictEqual(err, undefined); 421cb0ef41Sopenharmony_ci }); 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_ci // Stream ID 5 should never reach the server 451cb0ef41Sopenharmony_ci assert.notStrictEqual(stream.id, 5); 461cb0ef41Sopenharmony_ci 471cb0ef41Sopenharmony_ci}, 2)); 481cb0ef41Sopenharmony_ci 491cb0ef41Sopenharmony_ciserver.on('session', common.mustCall((session) => { 501cb0ef41Sopenharmony_ci session.on('error', common.expectsError({ 511cb0ef41Sopenharmony_ci code: 'ERR_HTTP2_ERROR', 521cb0ef41Sopenharmony_ci constructor: NghttpError, 531cb0ef41Sopenharmony_ci message: 'Stream was already closed or invalid' 541cb0ef41Sopenharmony_ci })); 551cb0ef41Sopenharmony_ci})); 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_ciconst settings = new h2test.SettingsFrame(); 581cb0ef41Sopenharmony_ciconst settingsAck = new h2test.SettingsFrame(true); 591cb0ef41Sopenharmony_ci// HeadersFrame(id, payload, padding, END_STREAM) 601cb0ef41Sopenharmony_ciconst id1 = new h2test.HeadersFrame(1, h2test.kFakeRequestHeaders, 0, true); 611cb0ef41Sopenharmony_ciconst id3 = new h2test.HeadersFrame(3, h2test.kFakeRequestHeaders, 0, true); 621cb0ef41Sopenharmony_ciconst id5 = new h2test.HeadersFrame(5, h2test.kFakeRequestHeaders, 0, true); 631cb0ef41Sopenharmony_ci 641cb0ef41Sopenharmony_ciserver.listen(0, () => { 651cb0ef41Sopenharmony_ci client = net.connect(server.address().port, () => { 661cb0ef41Sopenharmony_ci client.write(h2test.kClientMagic, () => { 671cb0ef41Sopenharmony_ci client.write(settings.data, () => { 681cb0ef41Sopenharmony_ci client.write(settingsAck.data); 691cb0ef41Sopenharmony_ci // Stream ID 1 frame will make it OK. 701cb0ef41Sopenharmony_ci client.write(id1.data, () => { 711cb0ef41Sopenharmony_ci // Stream ID 3 frame will make it OK. 721cb0ef41Sopenharmony_ci client.write(id3.data, () => { 731cb0ef41Sopenharmony_ci // A second Stream ID 1 frame should fail. 741cb0ef41Sopenharmony_ci // This will cause an error to occur because the client is 751cb0ef41Sopenharmony_ci // attempting to reuse an already closed stream. This must 761cb0ef41Sopenharmony_ci // cause the server session to be torn down. 771cb0ef41Sopenharmony_ci client.write(id1.data, () => { 781cb0ef41Sopenharmony_ci // This Stream ID 5 frame will never make it to the server 791cb0ef41Sopenharmony_ci client.write(id5.data); 801cb0ef41Sopenharmony_ci }); 811cb0ef41Sopenharmony_ci }); 821cb0ef41Sopenharmony_ci }); 831cb0ef41Sopenharmony_ci }); 841cb0ef41Sopenharmony_ci }); 851cb0ef41Sopenharmony_ci }); 861cb0ef41Sopenharmony_ci 871cb0ef41Sopenharmony_ci // An error may or may not be emitted on the client side, we don't care 881cb0ef41Sopenharmony_ci // either way if it is, but we don't want to die if it is. 891cb0ef41Sopenharmony_ci client.on('error', () => {}); 901cb0ef41Sopenharmony_ci client.on('close', common.mustCall(() => server.close())); 911cb0ef41Sopenharmony_ci client.resume(); 921cb0ef41Sopenharmony_ci}); 93