net,tls: add abort signal support to connect · nodejs/node@669b81c

1+

'use strict';

2+

const common = require('../common');

3+

const net = require('net');

4+

const assert = require('assert');

5+

const server = net.createServer();

6+

const { getEventListeners, once } = require('events');

7+8+

const liveConnections = new Set();

9+10+

server.listen(0, common.mustCall(async () => {

11+

const port = server.address().port;

12+

const host = 'localhost';

13+

const socketOptions = (signal) => ({ port, host, signal });

14+

server.on('connection', (connection) => {

15+

liveConnections.add(connection);

16+

connection.on('close', () => {

17+

liveConnections.delete(connection);

18+

});

19+

});

20+21+

const assertAbort = async (socket, testName) => {

22+

try {

23+

await once(socket, 'close');

24+

assert.fail(`close ${testName} should have thrown`);

25+

} catch (err) {

26+

assert.strictEqual(err.name, 'AbortError');

27+

}

28+

};

29+30+

async function postAbort() {

31+

const ac = new AbortController();

32+

const { signal } = ac;

33+

const socket = net.connect(socketOptions(signal));

34+

assert.strictEqual(getEventListeners(signal, 'abort').length, 1);

35+

ac.abort();

36+

await assertAbort(socket, 'postAbort');

37+

}

38+39+

async function preAbort() {

40+

const ac = new AbortController();

41+

const { signal } = ac;

42+

ac.abort();

43+

const socket = net.connect(socketOptions(signal));

44+

assert.strictEqual(getEventListeners(signal, 'abort').length, 0);

45+

await assertAbort(socket, 'preAbort');

46+

}

47+48+

async function tickAbort() {

49+

const ac = new AbortController();

50+

const { signal } = ac;

51+

setImmediate(() => ac.abort());

52+

const socket = net.connect(socketOptions(signal));

53+

assert.strictEqual(getEventListeners(signal, 'abort').length, 1);

54+

await assertAbort(socket, 'tickAbort');

55+

}

56+57+

async function testConstructor() {

58+

const ac = new AbortController();

59+

const { signal } = ac;

60+

ac.abort();

61+

const socket = new net.Socket(socketOptions(signal));

62+

assert.strictEqual(getEventListeners(signal, 'abort').length, 0);

63+

await assertAbort(socket, 'testConstructor');

64+

}

65+66+

async function testConstructorPost() {

67+

const ac = new AbortController();

68+

const { signal } = ac;

69+

const socket = new net.Socket(socketOptions(signal));

70+

assert.strictEqual(getEventListeners(signal, 'abort').length, 1);

71+

ac.abort();

72+

await assertAbort(socket, 'testConstructorPost');

73+

}

74+75+

async function testConstructorPostTick() {

76+

const ac = new AbortController();

77+

const { signal } = ac;

78+

const socket = new net.Socket(socketOptions(signal));

79+

assert.strictEqual(getEventListeners(signal, 'abort').length, 1);

80+

setImmediate(() => ac.abort());

81+

await assertAbort(socket, 'testConstructorPostTick');

82+

}

83+84+

await postAbort();

85+

await preAbort();

86+

await tickAbort();

87+

await testConstructor();

88+

await testConstructorPost();

89+

await testConstructorPostTick();

90+91+

// Killing the net.socket without connecting hangs the server.

92+

for (const connection of liveConnections) {

93+

connection.destroy();

94+

}

95+

server.close(common.mustCall());

96+

}));