• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2// Flags: --expose-internals
3
4const common = require('../common');
5const assert = require('assert');
6
7if (!common.hasCrypto)
8  common.skip('missing crypto');
9
10const h2 = require('http2');
11const net = require('net');
12const { NghttpError } = require('internal/http2/util');
13const h2test = require('../common/http2');
14let client;
15
16const server = h2.createServer();
17let gotFirstStreamId1;
18server.on('stream', common.mustCall((stream) => {
19  stream.respond();
20  stream.end('ok');
21
22  // Http2Server should be fast enough to respond to and close
23  // the first streams with ID 1 and ID 3 without errors.
24
25  // Test for errors in 'close' event to ensure no errors on some streams.
26  stream.on('error', () => {});
27  stream.on('close', (err) => {
28    if (stream.id === 1) {
29      if (gotFirstStreamId1) {
30        // We expect our outgoing frames to fail on Stream ID 1 the second time
31        // because a stream with ID 1 was already closed before.
32        common.expectsError({
33          constructor: NghttpError,
34          code: 'ERR_HTTP2_ERROR',
35          message: 'Stream was already closed or invalid'
36        });
37        return;
38      }
39      gotFirstStreamId1 = true;
40    }
41    assert.strictEqual(err, undefined);
42  });
43
44  // Stream ID 5 should never reach the server
45  assert.notStrictEqual(stream.id, 5);
46
47}, 2));
48
49server.on('session', common.mustCall((session) => {
50  session.on('error', common.expectsError({
51    code: 'ERR_HTTP2_ERROR',
52    constructor: NghttpError,
53    message: 'Stream was already closed or invalid'
54  }));
55}));
56
57const settings = new h2test.SettingsFrame();
58const settingsAck = new h2test.SettingsFrame(true);
59// HeadersFrame(id, payload, padding, END_STREAM)
60const id1 = new h2test.HeadersFrame(1, h2test.kFakeRequestHeaders, 0, true);
61const id3 = new h2test.HeadersFrame(3, h2test.kFakeRequestHeaders, 0, true);
62const id5 = new h2test.HeadersFrame(5, h2test.kFakeRequestHeaders, 0, true);
63
64server.listen(0, () => {
65  client = net.connect(server.address().port, () => {
66    client.write(h2test.kClientMagic, () => {
67      client.write(settings.data, () => {
68        client.write(settingsAck.data);
69        // Stream ID 1 frame will make it OK.
70        client.write(id1.data, () => {
71          // Stream ID 3 frame will make it OK.
72          client.write(id3.data, () => {
73            // A second Stream ID 1 frame should fail.
74            // This will cause an error to occur because the client is
75            // attempting to reuse an already closed stream. This must
76            // cause the server session to be torn down.
77            client.write(id1.data, () => {
78              // This Stream ID 5 frame will never make it to the server
79              client.write(id5.data);
80            });
81          });
82        });
83      });
84    });
85  });
86
87  // An error may or may not be emitted on the client side, we don't care
88  // either way if it is, but we don't want to die if it is.
89  client.on('error', () => {});
90  client.on('close', common.mustCall(() => server.close()));
91  client.resume();
92});
93