11
*/
12
export function findFreePort(startPort: number, giveUpAfter: number, timeout: number, stride = 1): Promise<number> {
14
>
15
>
return new Promise(resolve => {
16
>
const timeoutHandle = setTimeout(() => {
17
if (!done) {
18
done = true;
19
return resolve(0);
20
}
22
>
23
>
doFindFreePort(startPort, giveUpAfter, stride, (port) => {
24
>
if (!done) {
25
>
done = true;
26
>
clearTimeout(timeoutHandle);
27
>
return resolve(port);
28
>
}
29
>
});
30
>
});
31
>
}
32
33
>
function doFindFreePort(startPort: number, giveUpAfter: number, stride: number, clb: (port: number) => void): void {
ports.ts
34
>
if (giveUpAfter === 0) {
35
return clb(0);
36
}
38
>
const client = new net.Socket();
39
>
40
>
// If we can connect to the port it means the port is already taken so we continue searching
41
>
client.once('connect', () => {
42
dispose(client);
43
44
return doFindFreePort(startPort + stride, giveUpAfter - 1, stride, clb);
46
>
47
>
client.once('data', () => {
48
// this listener is required since node.js 8.x
50
>
51
>
client.once('error', (err: Error & { code?: string }) => {
52
>
dispose(client);
53
>
54
>
// If we receive any non ECONNREFUSED error, it means the port is used but we cannot connect
55
>
if (err.code !== 'ECONNREFUSED') {
56
return doFindFreePort(startPort + stride, giveUpAfter - 1, stride, clb);
57
}
59
>
// Otherwise it means the port is free to use!
60
>
return clb(startPort);
61
>
});
62
>
63
>
client.connect(startPort, '127.0.0.1');
64
>
}
65
66
// Reference: https://chromium.googlesource.com/chromium/src.git/+/refs/heads/main/net/base/port_util.cc#56