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