@remote.it/core
Version:
Core remote.it JavasScript/TypeScript library
61 lines (50 loc) • 1.58 kB
text/typescript
import net from 'net'
import debug from 'debug'
const d = debug('remoteit:PortScanner')
export interface PortScannerError extends Error {
code?: string
}
export class PortScanner {
public static async findFreePortInRange(
start: number,
end: number,
reservedPorts: number[] = []
): Promise<number | undefined> {
d('Checking port range:', { start, end })
// Create a range between start and end port numbers
const range = [...Array(end - start).keys()]
// Increment the ports from the starting port number
.map(x => x + start)
// Remove any reserved ports from our pool of ports
.filter(x => !reservedPorts.includes(x))
// Check if port is free, and if so, return it.
for (const port of range) {
const free = await this.isPortFree(port)
if (free) {
d('Found free port:', free)
return port
}
}
return undefined
}
public static async isPortFree(
port: number,
host: string = 'localhost'
): Promise<boolean> {
return new Promise(function(resolve) {
const server = net.createServer()
// Check if binding to port causes an exception
server.once('error', (err: PortScannerError) => {
if (err.code && (err.code === 'EADDRINUSE' || err.code === 'EACCES')) {
resolve(false)
}
})
// Listen for connection and resolve "true" if no errors
server.once('listening', () => {
server.once('close', () => resolve(true))
server.close()
})
server.listen(port, host)
})
}
}