@@ -2,6 +2,7 @@ import { Buffer } from 'buffer';
22import * as stream from 'stream' ;
33import * as fs from 'fs' ;
44import * as net from "net" ;
5+ import * as os from "os" ;
56import * as tls from "tls" ;
67import * as http from "http" ;
78import * as http2 from "http2" ;
@@ -103,19 +104,59 @@ import { SocksServerOptions } from "./socks-server";
103104
104105const serverPortCheckMutex = new Mutex ( ) ;
105106
107+ // Toggle this to test different port-finding strategies:
108+ // Toggle this to test different port-finding strategies:
109+ // - 'simple': single-host check (default, no deps)
110+ // - 'multi-host': check all local interfaces (like get-port does)
111+ // - 'get-port': use actual get-port package (dynamic import)
112+ // - 'get-port-preloaded': pre-import get-port at module load time (matches c59e07d)
113+ const PORT_FIND_MODE = ( process . env . PORT_FIND_MODE || 'simple' ) as
114+ 'simple' | 'multi-host' | 'get-port' | 'get-port-preloaded' ;
115+
116+ // Pre-load get-port at module load time (like the static import in c59e07d)
117+ const preloadedGetPort = PORT_FIND_MODE === 'get-port-preloaded'
118+ ? require ( 'get-port' ) as { default : Function , portNumbers : Function }
119+ : null ;
120+
106121async function findFreePort ( startPort : number , endPort : number ) : Promise < number > {
122+ if ( PORT_FIND_MODE === 'get-port' ) {
123+ const { default : getPort , portNumbers } = await import ( 'get-port' ) ;
124+ return getPort ( { port : portNumbers ( startPort , endPort ) } ) ;
125+ }
126+
127+ if ( PORT_FIND_MODE === 'get-port-preloaded' ) {
128+ return preloadedGetPort ! . default ( { port : preloadedGetPort ! . portNumbers ( startPort , endPort ) } ) ;
129+ }
130+
131+ const hosts : Array < string | undefined > = PORT_FIND_MODE === 'multi-host'
132+ ? ( ( ) => {
133+ const results : Array < string | undefined > = [ undefined , '0.0.0.0' ] ;
134+ for ( const iface of Object . values ( os . networkInterfaces ( ) ) ) {
135+ for ( const config of iface ! ) results . push ( config . address ) ;
136+ }
137+ return results ;
138+ } ) ( )
139+ : [ undefined ] ; // 'simple' mode: just default host
140+
107141 for ( let port = startPort ; port <= endPort ; port ++ ) {
108142 try {
109- await new Promise < void > ( ( resolve , reject ) => {
110- const server = net . createServer ( ) ;
111- server . unref ( ) ;
112- server . once ( 'error' , reject ) ;
113- server . once ( 'listening' , ( ) => server . close ( ( ) => resolve ( ) ) ) ;
114- server . listen ( port ) ;
115- } ) ;
143+ for ( const host of hosts ) {
144+ await new Promise < void > ( ( resolve , reject ) => {
145+ const server = net . createServer ( ) ;
146+ server . unref ( ) ;
147+ server . once ( 'error' , reject ) ;
148+ server . once ( 'listening' , ( ) => server . close ( ( ) => resolve ( ) ) ) ;
149+ if ( host !== undefined ) {
150+ server . listen ( port , host ) ;
151+ } else {
152+ server . listen ( port ) ;
153+ }
154+ } ) ;
155+ }
116156 return port ;
117157 } catch ( e : any ) {
118- if ( e . code !== 'EADDRINUSE' && e . code !== 'EACCES' ) throw e ;
158+ if ( e . code !== 'EADDRINUSE' && e . code !== 'EACCES' &&
159+ e . code !== 'EADDRNOTAVAIL' && e . code !== 'EINVAL' ) throw e ;
119160 }
120161 }
121162 throw new Error ( `No open ports between ${ startPort } and ${ endPort } ` ) ;
0 commit comments