• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2const common = require('../common');
3if (!common.hasCrypto)
4  common.skip('missing crypto');
5const assert = require('assert');
6const fixtures = require('../common/fixtures');
7const http2 = require('http2');
8
9// This test assesses whether long-running writes can complete
10// or timeout because the session or stream are not aware that the
11// backing stream is still writing.
12// To simulate a slow client, we write a really large chunk and
13// then proceed through the following cycle:
14// 1) Receive first 'data' event and record currently written size
15// 2) Once we've read up to currently written size recorded above,
16//    we pause the stream and wait longer than the server timeout
17// 3) Socket.prototype._onTimeout triggers and should confirm
18//    that the backing stream is still active and writing
19// 4) Our timer fires, we resume the socket and start at 1)
20
21const writeSize = 3000000;
22const minReadSize = 500000;
23const serverTimeout = common.platformTimeout(500);
24let offsetTimeout = common.platformTimeout(100);
25let didReceiveData = false;
26
27const server = http2.createSecureServer({
28  key: fixtures.readKey('agent1-key.pem'),
29  cert: fixtures.readKey('agent1-cert.pem')
30});
31server.on('stream', common.mustCall((stream) => {
32  const content = Buffer.alloc(writeSize, 0x44);
33
34  stream.respond({
35    'Content-Type': 'application/octet-stream',
36    'Content-Length': content.length.toString(),
37    'Vary': 'Accept-Encoding'
38  });
39
40  stream.write(content);
41  stream.setTimeout(serverTimeout);
42  stream.on('timeout', () => {
43    assert.ok(!didReceiveData, 'Should not timeout');
44  });
45  stream.end();
46}));
47server.setTimeout(serverTimeout);
48server.on('timeout', () => {
49  assert.ok(!didReceiveData, 'Should not timeout');
50});
51
52server.listen(0, common.mustCall(() => {
53  const client = http2.connect(`https://localhost:${server.address().port}`,
54                               { rejectUnauthorized: false });
55
56  const req = client.request({ ':path': '/' });
57  req.end();
58
59  const resume = () => req.resume();
60  let receivedBufferLength = 0;
61  let firstReceivedAt;
62  req.on('data', common.mustCallAtLeast((buf) => {
63    if (receivedBufferLength === 0) {
64      didReceiveData = false;
65      firstReceivedAt = Date.now();
66    }
67    receivedBufferLength += buf.length;
68    if (receivedBufferLength >= minReadSize &&
69        receivedBufferLength < writeSize) {
70      didReceiveData = true;
71      receivedBufferLength = 0;
72      req.pause();
73      setTimeout(
74        resume,
75        serverTimeout + offsetTimeout - (Date.now() - firstReceivedAt)
76      );
77      offsetTimeout = 0;
78    }
79  }, 1));
80  req.on('end', common.mustCall(() => {
81    client.close();
82    server.close();
83  }));
84}));
85