Repository: node
Issue: net.createConnection does not have a connection timeout.
Labels: net

I was trying to troubleshoot some TCP connect issue that the TCP server doesn't reply a `ACK` or `RST`.

So I write a simple test code to connect a port which doesn't have any service. 

```javascript
const net = require('net');

const SocketTimeout = 1000;
const StartTime = Date.now();

function print(msg, ...args) {
  const cost = Date.now() - StartTime;
  console.log(`[+${cost}ms]`, msg, `with ${args.length} args`, args);
}

const opt = { host: '127.0.0.1', port: 12345 };

const conn = net.createConnection(opt, () =>  print('create connection'));
conn.setTimeout(1000);

print('Socket Timeout: ' + SocketTimeout);
conn.on('connect', (...args) => print('$connect$', ...args));
conn.on('timeout', (...args) => print('$timeout$', ...args));
conn.on('error', (e) => print('$error$', e));
conn.on('close', (...args) => print('$close$', ...args));
conn.on('end', (...args) => print('$end$', ...args));
```

Normally, it will return an `ECONNREFUSED` error which is expected (because TCP will recevie a `RST` packet). Like this:

```
[+4ms] Socket Timeout: 1000 with 0 args []
[+11ms] $error$ with 1 args [ { Error: connect ECONNREFUSED 127.0.0.1:12345
      at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1104:14)
    errno: 'ECONNREFUSED',
    code: 'ECONNREFUSED',
    syscall: 'connect',
    address: '127.0.0.1',
    port: 12345 } ]
[+15ms] $close$ with 1 args [ true ]
```

I'm trying to represent the situation that a TCP server doesn't reply a `RST`.

So I changed the iptables rules, like this:

```
iptables -I OUTPUT -p tcp --tcp-flags ALL RST,ACK -j DROP
```

and run the code again:

```
[+3ms] Socket Timeout: 1000 with 0 args []
[+1004ms] $timeout$ with 0 args []
[+132620ms] $error$ with 1 args [ { Error: connect ETIMEDOUT 127.0.0.1:12345
      at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1107:14)
    errno: 'ETIMEDOUT',
    code: 'ETIMEDOUT',
    syscall: 'connect',
    address: '127.0.0.1',
    port: 12345 } ]
[+132730ms] $close$ with 1 args [ true ]
```

`timeout` event was emitted in 1000ms as expected, but `error` event was emitted in 132620ms.

and here is the tcpdump logs:

```
20:41:34.746042 IP 127.0.0.1.47230 > 127.0.0.1.12345: Flags [S], seq 2918343672, win 43690, options [mss 65495,sackOK,TS val 4291343189 ecr 0,nop,wscale 7], length 0
20:41:35.764631 IP 127.0.0.1.47230 > 127.0.0.1.12345: Flags [S], seq 2918343672, win 43690, options [mss 65495,sackOK,TS val 4291344208 ecr 0,nop,wscale 7], length 0
20:41:37.780633 IP 127.0.0.1.47230 > 127.0.0.1.12345: Flags [S], seq 2918343672, win 43690, options [mss 65495,sackOK,TS val 4291346224 ecr 0,nop,wscale 7], length 0
20:41:41.908635 IP 127.0.0.1.47230 > 127.0.0.1.12345: Flags [S], seq 2918343672, win 43690, options [mss 65495,sackOK,TS val 4291350352 ecr 0,nop,wscale 7], length 0
20:41:50.100621 IP 127.0.0.1.47230 > 127.0.0.1.12345: Flags [S], seq 2918343672, win 43690, options [mss 65495,sackOK,TS val 4291358544 ecr 0,nop,wscale 7], length 0
20:42:06.228631 IP 127.0.0.1.47230 > 127.0.0.1.12345: Flags [S], seq 2918343672, win 43690, options [mss 65495,sackOK,TS val 4291374672 ecr 0,nop,wscale 7], length 0
20:42:40.020636 IP 127.0.0.1.47230 > 127.0.0.1.12345: Flags [S], seq 2918343672, win 43690, options [mss 65495,sackOK,TS val 4291408464 ecr 0,nop,wscale 7], length 0
```

So basically, there is no way to separate connection timeout and the socket timeout.



Ref: https://github.com/nodejs/node/issues/5757