11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ciconst common = require('../common');
31cb0ef41Sopenharmony_ciif (!common.hasCrypto)
41cb0ef41Sopenharmony_ci  common.skip('missing crypto');
51cb0ef41Sopenharmony_ciconst assert = require('assert');
61cb0ef41Sopenharmony_ciconst fixtures = require('../common/fixtures');
71cb0ef41Sopenharmony_ciconst http2 = require('http2');
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ci// This test assesses whether long-running writes can complete
101cb0ef41Sopenharmony_ci// or timeout because the session or stream are not aware that the
111cb0ef41Sopenharmony_ci// backing stream is still writing.
121cb0ef41Sopenharmony_ci// To simulate a slow client, we write a really large chunk and
131cb0ef41Sopenharmony_ci// then proceed through the following cycle:
141cb0ef41Sopenharmony_ci// 1) Receive first 'data' event and record currently written size
151cb0ef41Sopenharmony_ci// 2) Once we've read up to currently written size recorded above,
161cb0ef41Sopenharmony_ci//    we pause the stream and wait longer than the server timeout
171cb0ef41Sopenharmony_ci// 3) Socket.prototype._onTimeout triggers and should confirm
181cb0ef41Sopenharmony_ci//    that the backing stream is still active and writing
191cb0ef41Sopenharmony_ci// 4) Our timer fires, we resume the socket and start at 1)
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ciconst writeSize = 3000000;
221cb0ef41Sopenharmony_ciconst minReadSize = 500000;
231cb0ef41Sopenharmony_ciconst serverTimeout = common.platformTimeout(500);
241cb0ef41Sopenharmony_cilet offsetTimeout = common.platformTimeout(100);
251cb0ef41Sopenharmony_cilet didReceiveData = false;
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ciconst server = http2.createSecureServer({
281cb0ef41Sopenharmony_ci  key: fixtures.readKey('agent1-key.pem'),
291cb0ef41Sopenharmony_ci  cert: fixtures.readKey('agent1-cert.pem')
301cb0ef41Sopenharmony_ci});
311cb0ef41Sopenharmony_ciserver.on('stream', common.mustCall((stream) => {
321cb0ef41Sopenharmony_ci  const content = Buffer.alloc(writeSize, 0x44);
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci  stream.respond({
351cb0ef41Sopenharmony_ci    'Content-Type': 'application/octet-stream',
361cb0ef41Sopenharmony_ci    'Content-Length': content.length.toString(),
371cb0ef41Sopenharmony_ci    'Vary': 'Accept-Encoding'
381cb0ef41Sopenharmony_ci  });
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci  stream.write(content);
411cb0ef41Sopenharmony_ci  stream.setTimeout(serverTimeout);
421cb0ef41Sopenharmony_ci  stream.on('timeout', () => {
431cb0ef41Sopenharmony_ci    assert.ok(!didReceiveData, 'Should not timeout');
441cb0ef41Sopenharmony_ci  });
451cb0ef41Sopenharmony_ci  stream.end();
461cb0ef41Sopenharmony_ci}));
471cb0ef41Sopenharmony_ciserver.setTimeout(serverTimeout);
481cb0ef41Sopenharmony_ciserver.on('timeout', () => {
491cb0ef41Sopenharmony_ci  assert.ok(!didReceiveData, 'Should not timeout');
501cb0ef41Sopenharmony_ci});
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ciserver.listen(0, common.mustCall(() => {
531cb0ef41Sopenharmony_ci  const client = http2.connect(`https://localhost:${server.address().port}`,
541cb0ef41Sopenharmony_ci                               { rejectUnauthorized: false });
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ci  const req = client.request({ ':path': '/' });
571cb0ef41Sopenharmony_ci  req.end();
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ci  const resume = () => req.resume();
601cb0ef41Sopenharmony_ci  let receivedBufferLength = 0;
611cb0ef41Sopenharmony_ci  let firstReceivedAt;
621cb0ef41Sopenharmony_ci  req.on('data', common.mustCallAtLeast((buf) => {
631cb0ef41Sopenharmony_ci    if (receivedBufferLength === 0) {
641cb0ef41Sopenharmony_ci      didReceiveData = false;
651cb0ef41Sopenharmony_ci      firstReceivedAt = Date.now();
661cb0ef41Sopenharmony_ci    }
671cb0ef41Sopenharmony_ci    receivedBufferLength += buf.length;
681cb0ef41Sopenharmony_ci    if (receivedBufferLength >= minReadSize &&
691cb0ef41Sopenharmony_ci        receivedBufferLength < writeSize) {
701cb0ef41Sopenharmony_ci      didReceiveData = true;
711cb0ef41Sopenharmony_ci      receivedBufferLength = 0;
721cb0ef41Sopenharmony_ci      req.pause();
731cb0ef41Sopenharmony_ci      setTimeout(
741cb0ef41Sopenharmony_ci        resume,
751cb0ef41Sopenharmony_ci        serverTimeout + offsetTimeout - (Date.now() - firstReceivedAt)
761cb0ef41Sopenharmony_ci      );
771cb0ef41Sopenharmony_ci      offsetTimeout = 0;
781cb0ef41Sopenharmony_ci    }
791cb0ef41Sopenharmony_ci  }, 1));
801cb0ef41Sopenharmony_ci  req.on('end', common.mustCall(() => {
811cb0ef41Sopenharmony_ci    client.close();
821cb0ef41Sopenharmony_ci    server.close();
831cb0ef41Sopenharmony_ci  }));
841cb0ef41Sopenharmony_ci}));
85