1'use strict';
2const common = require('../common');
3if (!common.hasCrypto) common.skip('missing crypto');
4const fixtures = require('../common/fixtures');
5
6// An HTTP Agent reuses a TLSSocket, and makes a failed call to `asyncReset`.
7// Refs: https://github.com/nodejs/node/issues/13045
8
9const assert = require('assert');
10const https = require('https');
11
12const serverOptions = {
13  key: fixtures.readKey('agent1-key.pem'),
14  cert: fixtures.readKey('agent1-cert.pem'),
15  ca: fixtures.readKey('ca1-cert.pem')
16};
17
18const server = https.createServer(
19  serverOptions,
20  common.mustCall((req, res) => {
21    res.end('hello world\n');
22  }, 2)
23);
24
25server.listen(
26  0,
27  common.mustCall(function() {
28    const port = this.address().port;
29    const clientOptions = {
30      agent: new https.Agent({
31        keepAlive: true,
32        rejectUnauthorized: false
33      }),
34      port: port
35    };
36
37    const req = https.get(
38      clientOptions,
39      common.mustCall((res) => {
40        assert.strictEqual(res.statusCode, 200);
41        res.on('error', (err) => assert.fail(err));
42        res.socket.on('error', (err) => assert.fail(err));
43        res.resume();
44        // Drain the socket and wait for it to be free to reuse
45        res.socket.once('free', () => {
46          // This is the pain point. Internally the Agent will call
47          // `socket._handle.asyncReset()` and if the _handle does not implement
48          // `asyncReset` this will throw TypeError
49          const req2 = https.get(
50            clientOptions,
51            common.mustCall((res2) => {
52              assert.strictEqual(res.statusCode, 200);
53              res2.on('error', (err) => assert.fail(err));
54              res2.socket.on('error', (err) => assert.fail(err));
55              // This should be the end of the test
56              res2.destroy();
57              server.close();
58            })
59          );
60          req2.on('error', (err) => assert.fail(err));
61        });
62      })
63    );
64    req.on('error', (err) => assert.fail(err));
65  })
66);
67