@@ -9,6 +9,26 @@ const debug = Debug('ionic:cli-framework:utils:network');
99
1010export const ERROR_NETWORK_ADDRESS_NOT_AVAIL = 'NETWORK_ADDRESS_NOT_AVAIL' ;
1111
12+ export const DEFAULT_ADDRESSES : ReadonlyArray < string > = getDefaultAddresses ( ) ;
13+
14+ function getDefaultAddresses ( ) : string [ ] {
15+ const addresses : string [ ] = [ '0.0.0.0' ] ;
16+
17+ try {
18+ const networkInterfaces = os . networkInterfaces ( ) ;
19+
20+ for ( const device of Object . keys ( networkInterfaces ) ) {
21+ const networkInterface = networkInterfaces [ device ] ;
22+
23+ addresses . push ( ...networkInterface . map ( i => i . address ) ) ;
24+ }
25+ } catch ( e ) {
26+ // swallow
27+ }
28+
29+ return addresses ;
30+ }
31+
1232export function getExternalIPv4Interfaces ( ) : NetworkInterface [ ] {
1333 const networkInterfaces = os . networkInterfaces ( ) ;
1434 const devices : NetworkInterface [ ] = [ ] ;
@@ -26,9 +46,17 @@ export function getExternalIPv4Interfaces(): NetworkInterface[] {
2646 return devices ;
2747}
2848
29- export async function findClosestOpenPort ( port : number , host ?: string ) : Promise < number > {
49+ /**
50+ * Attempts to locate a port number starting from `port` and incrementing by 1.
51+ *
52+ * This function looks through all internal network interfaces, attempting
53+ * host/port combinations until it finds an available port on all interfaces.
54+ *
55+ * @param port The port at which to start checking.
56+ */
57+ export async function findClosestOpenPort ( port : number ) : Promise < number > {
3058 async function t ( portToCheck : number ) : Promise < number > {
31- if ( await isPortAvailable ( portToCheck , host ) ) {
59+ if ( await isPortAvailable ( portToCheck ) ) {
3260 return portToCheck ;
3361 }
3462
@@ -38,7 +66,33 @@ export async function findClosestOpenPort(port: number, host?: string): Promise<
3866 return t ( port ) ;
3967}
4068
41- export async function isPortAvailable ( port : number , host ?: string ) : Promise < boolean > {
69+ /**
70+ * Checks whether a port is open or closed.
71+ *
72+ * This function looks through all internal network interfaces, checking
73+ * whether all host/port combinations are open. If one or more is not, the port
74+ * is not available.
75+ */
76+ export async function isPortAvailable ( port : number ) : Promise < boolean > {
77+ let available = true ;
78+
79+ for ( const address of DEFAULT_ADDRESSES ) {
80+ try {
81+ debug ( 'checking for open port on %s:%d' , address , port ) ;
82+ available = await isPortAvailableForHost ( address , port ) ;
83+
84+ if ( ! available ) {
85+ return false ;
86+ }
87+ } catch ( e ) {
88+ debug ( 'error while checking %s:%d: %o' , address , port , e ) ;
89+ }
90+ }
91+
92+ return available ;
93+ }
94+
95+ export function isPortAvailableForHost ( host : string , port : number ) : Promise < boolean > {
4296 return new Promise < boolean > ( ( resolve , reject ) => {
4397 const tester = net . createServer ( )
4498 . once ( 'error' , ( err : any ) => {
0 commit comments