• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Flags: --expose-internals
2
3'use strict';
4
5const common = require('../common');
6if (!common.hasCrypto)
7  common.skip('missing crypto');
8const assert = require('assert');
9const h2 = require('http2');
10const net = require('net');
11const util = require('util');
12
13const { kTimeout } = require('internal/timers');
14
15// Tests behavior of the proxied socket on Http2Session
16
17const errMsg = {
18  code: 'ERR_HTTP2_NO_SOCKET_MANIPULATION',
19  name: 'Error',
20  message: 'HTTP/2 sockets should not be directly manipulated ' +
21           '(e.g. read and written)'
22};
23
24const server = h2.createServer();
25
26server.on('stream', common.mustCall(function(stream, headers) {
27  const socket = stream.session.socket;
28  const session = stream.session;
29
30  assert.ok(socket instanceof net.Socket);
31
32  assert.strictEqual(socket.writable, true);
33  assert.strictEqual(socket.readable, true);
34  assert.strictEqual(typeof socket.address(), 'object');
35
36  socket.setTimeout(987);
37  assert.strictEqual(session[kTimeout]._idleTimeout, 987);
38
39  // The indentation is corrected depending on the depth.
40  let inspectedTimeout = util.inspect(session[kTimeout]);
41  assert(inspectedTimeout.includes('  _idlePrev: [TimersList]'));
42  assert(inspectedTimeout.includes('  _idleNext: [TimersList]'));
43  assert(!inspectedTimeout.includes('   _idleNext: [TimersList]'));
44
45  inspectedTimeout = util.inspect([ session[kTimeout] ]);
46  assert(inspectedTimeout.includes('    _idlePrev: [TimersList]'));
47  assert(inspectedTimeout.includes('    _idleNext: [TimersList]'));
48  assert(!inspectedTimeout.includes('     _idleNext: [TimersList]'));
49
50  const inspectedTimersList = util.inspect([[ session[kTimeout]._idlePrev ]]);
51  assert(inspectedTimersList.includes('      _idlePrev: [Timeout]'));
52  assert(inspectedTimersList.includes('      _idleNext: [Timeout]'));
53  assert(!inspectedTimersList.includes('       _idleNext: [Timeout]'));
54
55  assert.throws(() => socket.destroy, errMsg);
56  assert.throws(() => socket.emit, errMsg);
57  assert.throws(() => socket.end, errMsg);
58  assert.throws(() => socket.pause, errMsg);
59  assert.throws(() => socket.read, errMsg);
60  assert.throws(() => socket.resume, errMsg);
61  assert.throws(() => socket.write, errMsg);
62  assert.throws(() => socket.setEncoding, errMsg);
63  assert.throws(() => socket.setKeepAlive, errMsg);
64  assert.throws(() => socket.setNoDelay, errMsg);
65
66  assert.throws(() => (socket.destroy = undefined), errMsg);
67  assert.throws(() => (socket.emit = undefined), errMsg);
68  assert.throws(() => (socket.end = undefined), errMsg);
69  assert.throws(() => (socket.pause = undefined), errMsg);
70  assert.throws(() => (socket.read = undefined), errMsg);
71  assert.throws(() => (socket.resume = undefined), errMsg);
72  assert.throws(() => (socket.write = undefined), errMsg);
73  assert.throws(() => (socket.setEncoding = undefined), errMsg);
74  assert.throws(() => (socket.setKeepAlive = undefined), errMsg);
75  assert.throws(() => (socket.setNoDelay = undefined), errMsg);
76
77  // Resetting the socket listeners to their own value should not throw.
78  socket.on = socket.on;  // eslint-disable-line no-self-assign
79  socket.once = socket.once;  // eslint-disable-line no-self-assign
80
81  socket.unref();
82  assert.strictEqual(socket._handle.hasRef(), false);
83  socket.ref();
84  assert.strictEqual(socket._handle.hasRef(), true);
85
86  stream.respond();
87
88  socket.writable = true;
89  socket.readable = true;
90  assert.strictEqual(socket.writable, true);
91  assert.strictEqual(socket.readable, true);
92  socket.writable = false;
93  socket.readable = false;
94  assert.strictEqual(socket.writable, false);
95  assert.strictEqual(socket.readable, false);
96
97  stream.end();
98
99  // Setting socket properties sets the session properties correctly.
100  const fn = () => {};
101  socket.setTimeout = fn;
102  assert.strictEqual(session.setTimeout, fn);
103
104  socket.ref = fn;
105  assert.strictEqual(session.ref, fn);
106
107  socket.unref = fn;
108  assert.strictEqual(session.unref, fn);
109
110  stream.session.on('close', common.mustCall(() => {
111    assert.strictEqual(session.socket, undefined);
112  }));
113}));
114
115server.listen(0, common.mustCall(function() {
116  const port = server.address().port;
117  const url = `http://localhost:${port}`;
118  const client = h2.connect(url, common.mustCall(() => {
119    const request = client.request();
120    request.on('end', common.mustCall(() => {
121      client.close();
122      server.close();
123    }));
124    request.resume();
125  }));
126}));
127