11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst common = require('../common');
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ciif (!common.hasCrypto)
61cb0ef41Sopenharmony_ci  common.skip('missing crypto');
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ciconst h2 = require('http2');
91cb0ef41Sopenharmony_ciconst net = require('net');
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_ciconst preamble = Buffer.from([
121cb0ef41Sopenharmony_ci  0x50, 0x52, 0x49, 0x20, 0x2a, 0x20, 0x48, 0x54, 0x54, 0x50, 0x2f,
131cb0ef41Sopenharmony_ci  0x32, 0x2e, 0x30, 0x0d, 0x0a, 0x0d, 0x0a, 0x53, 0x4d, 0x0d, 0x0a,
141cb0ef41Sopenharmony_ci  0x0d, 0x0a, 0x00, 0x00, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
151cb0ef41Sopenharmony_ci  0x00, 0x03, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0x00, 0xff,
161cb0ef41Sopenharmony_ci  0xff, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
171cb0ef41Sopenharmony_ci  0x00, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
181cb0ef41Sopenharmony_ci  0x00, 0xc8, 0x00, 0x00, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00, 0x05,
191cb0ef41Sopenharmony_ci  0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x05, 0x02, 0x00, 0x00,
201cb0ef41Sopenharmony_ci  0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
211cb0ef41Sopenharmony_ci  0x02, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x07, 0x00,
221cb0ef41Sopenharmony_ci  0x00, 0x00, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00,
231cb0ef41Sopenharmony_ci  0x00, 0x03, 0x00, 0x00, 0x00, 0x2c, 0x01, 0x24, 0x00, 0x00, 0x00,
241cb0ef41Sopenharmony_ci  0x0d, 0x00, 0x00, 0x00, 0x0b, 0x0f, 0x83, 0x84, 0x86, 0x41, 0x8a,
251cb0ef41Sopenharmony_ci  0xa0, 0xe4, 0x1d, 0x13, 0x9d, 0x09, 0xb8, 0xf0, 0x1e, 0x07, 0x53,
261cb0ef41Sopenharmony_ci  0x03, 0x2a, 0x2f, 0x2a, 0x90, 0x7a, 0x8a, 0xaa, 0x69, 0xd2, 0x9a,
271cb0ef41Sopenharmony_ci  0xc4, 0xc0, 0x57, 0x0b, 0xcb, 0x87, 0x0f, 0x0d, 0x83, 0x08, 0x00,
281cb0ef41Sopenharmony_ci  0x0f,
291cb0ef41Sopenharmony_ci]);
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ciconst data = Buffer.from([
321cb0ef41Sopenharmony_ci  0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d,
331cb0ef41Sopenharmony_ci  0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x0a, 0x68, 0x65, 0x6c,
341cb0ef41Sopenharmony_ci  0x6c, 0x6f, 0x0a, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x0a,
351cb0ef41Sopenharmony_ci  0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d,
361cb0ef41Sopenharmony_ci  0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x0a, 0x68, 0x65, 0x6c,
371cb0ef41Sopenharmony_ci  0x6c, 0x6f, 0x0a, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x0a,
381cb0ef41Sopenharmony_ci  0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d,
391cb0ef41Sopenharmony_ci  0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x0a, 0x68, 0x65, 0x6c,
401cb0ef41Sopenharmony_ci  0x6c, 0x6f, 0x0a, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x0a,
411cb0ef41Sopenharmony_ci  0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d,
421cb0ef41Sopenharmony_ci  0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x0a, 0x68, 0x65, 0x6c,
431cb0ef41Sopenharmony_ci  0x6c, 0x6f, 0x0a, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x0a,
441cb0ef41Sopenharmony_ci  0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d,
451cb0ef41Sopenharmony_ci  0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x0a, 0x68, 0x65, 0x6c,
461cb0ef41Sopenharmony_ci  0x6c, 0x6f, 0x0a, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x0a,
471cb0ef41Sopenharmony_ci  0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d,
481cb0ef41Sopenharmony_ci  0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x0a, 0x68, 0x65, 0x6c,
491cb0ef41Sopenharmony_ci  0x6c, 0x6f, 0x0a, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x0a,
501cb0ef41Sopenharmony_ci]);
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ci// This is testing the case of a misbehaving client that is not paying
531cb0ef41Sopenharmony_ci// attention to flow control. The initial window size is set to data
541cb0ef41Sopenharmony_ci// payload, which in this case is 18, the stream is set to flowing so
551cb0ef41Sopenharmony_ci// WINDOW_UPDATE frames are being sent, but the client is writing
561cb0ef41Sopenharmony_ci// faster than those can be read.
571cb0ef41Sopenharmony_ci//
581cb0ef41Sopenharmony_ci// Bad client! Bad!
591cb0ef41Sopenharmony_ci//
601cb0ef41Sopenharmony_ci// Fortunately, nghttp2 handles this situation for us by keeping track
611cb0ef41Sopenharmony_ci// of the flow control window and responding with a FLOW_CONTROL_ERROR
621cb0ef41Sopenharmony_ci// causing the stream to get shut down...
631cb0ef41Sopenharmony_ci//
641cb0ef41Sopenharmony_ci// At least, that's what is supposed to happen.
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_cilet client;
671cb0ef41Sopenharmony_ciconst server = h2.createServer({ settings: { initialWindowSize: 18 } });
681cb0ef41Sopenharmony_ciserver.on('stream', (stream) => {
691cb0ef41Sopenharmony_ci  stream.on('error', common.expectsError({
701cb0ef41Sopenharmony_ci    code: 'ERR_HTTP2_STREAM_ERROR',
711cb0ef41Sopenharmony_ci    name: 'Error',
721cb0ef41Sopenharmony_ci    message: 'Stream closed with error code NGHTTP2_FLOW_CONTROL_ERROR'
731cb0ef41Sopenharmony_ci  }));
741cb0ef41Sopenharmony_ci  stream.on('close', common.mustCall(() => {
751cb0ef41Sopenharmony_ci    server.close(common.mustCall());
761cb0ef41Sopenharmony_ci    client.destroy();
771cb0ef41Sopenharmony_ci  }));
781cb0ef41Sopenharmony_ci  stream.resume();
791cb0ef41Sopenharmony_ci  stream.respond();
801cb0ef41Sopenharmony_ci  stream.end('ok');
811cb0ef41Sopenharmony_ci});
821cb0ef41Sopenharmony_ci
831cb0ef41Sopenharmony_ciserver.on('close', common.mustCall());
841cb0ef41Sopenharmony_ci
851cb0ef41Sopenharmony_ciserver.listen(0, () => {
861cb0ef41Sopenharmony_ci  client = net.connect(server.address().port, () => {
871cb0ef41Sopenharmony_ci    client.write(preamble);
881cb0ef41Sopenharmony_ci    client.write(data);
891cb0ef41Sopenharmony_ci    client.write(data);
901cb0ef41Sopenharmony_ci  });
911cb0ef41Sopenharmony_ci});
92