socket-function 1.2.4 → 1.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/webSocketServer.ts +44 -35
package/package.json
CHANGED
package/src/webSocketServer.ts
CHANGED
|
@@ -20,6 +20,12 @@ import { formatTime } from "./formatting/format";
|
|
|
20
20
|
import { getExternalIP, testTCPIsListening } from "./networking";
|
|
21
21
|
import { forwardPort } from "./forwardPort";
|
|
22
22
|
|
|
23
|
+
// When a requested port is taken and useAvailablePortIfPortInUse is set, we scan
|
|
24
|
+
// upwards from this base instead of binding a random OS-assigned port, so restarts
|
|
25
|
+
// land on predictable, consistent ports.
|
|
26
|
+
const PORT_SCAN_START = 13000;
|
|
27
|
+
const PORT_SCAN_COUNT = 10000;
|
|
28
|
+
|
|
23
29
|
export type SocketServerConfig = (
|
|
24
30
|
https.ServerOptions & {
|
|
25
31
|
key: string | Buffer;
|
|
@@ -311,52 +317,55 @@ export async function startSocketServer(
|
|
|
311
317
|
|
|
312
318
|
let port = config.port;
|
|
313
319
|
if (!SocketFunction.silent) {
|
|
314
|
-
console.log(yellow(`Trying to
|
|
320
|
+
console.log(yellow(`Trying to listen on ${host}:${port}`));
|
|
315
321
|
}
|
|
316
322
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
//
|
|
321
|
-
async function
|
|
323
|
+
// Attempts to bind realServer to a single port. Resolves true once the server is
|
|
324
|
+
// actually listening, false if the port is already in use, and rejects on any
|
|
325
|
+
// other error. After an EADDRINUSE the server is still usable, so the caller can
|
|
326
|
+
// simply retry listen() on the next candidate.
|
|
327
|
+
async function tryListen(candidatePort: number): Promise<boolean> {
|
|
322
328
|
return await new Promise<boolean>((resolve, reject) => {
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
realServer.once("listening", () => {
|
|
327
|
-
resolve(false);
|
|
328
|
-
});
|
|
329
|
-
});
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
if (config.useAvailablePortIfPortInUse && port) {
|
|
333
|
-
realServer.listen(port, host);
|
|
334
|
-
let isListening = await new Promise<boolean>((resolve, reject) => {
|
|
335
|
-
if (realServer.listening) {
|
|
336
|
-
resolve(true);
|
|
337
|
-
return;
|
|
329
|
+
function cleanup() {
|
|
330
|
+
realServer.removeListener("error", onError);
|
|
331
|
+
realServer.removeListener("listening", onListening);
|
|
338
332
|
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
333
|
+
function onError(e: NodeJS.ErrnoException) {
|
|
334
|
+
cleanup();
|
|
335
|
+
if (e.code === "EADDRINUSE" || e.message.includes("EADDRINUSE")) {
|
|
336
|
+
resolve(false);
|
|
342
337
|
} else {
|
|
343
338
|
reject(e);
|
|
344
339
|
}
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
340
|
+
}
|
|
341
|
+
function onListening() {
|
|
342
|
+
cleanup();
|
|
343
|
+
resolve(true);
|
|
344
|
+
}
|
|
345
|
+
realServer.once("error", onError);
|
|
346
|
+
realServer.once("listening", onListening);
|
|
347
|
+
realServer.listen(candidatePort, host);
|
|
349
348
|
});
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
let bound = await tryListen(port);
|
|
352
|
+
if (!bound && config.useAvailablePortIfPortInUse) {
|
|
353
|
+
for (let candidate = PORT_SCAN_START; candidate < PORT_SCAN_START + PORT_SCAN_COUNT; candidate++) {
|
|
354
|
+
if (candidate === port) continue;
|
|
355
|
+
if (await tryListen(candidate)) {
|
|
356
|
+
bound = true;
|
|
357
|
+
port = candidate;
|
|
358
|
+
break;
|
|
359
|
+
}
|
|
354
360
|
}
|
|
355
|
-
|
|
356
|
-
|
|
361
|
+
if (!bound) {
|
|
362
|
+
throw new Error(`Could not find an available port in range ${PORT_SCAN_START}-${PORT_SCAN_START + PORT_SCAN_COUNT - 1} (requested ${config.port})`);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
if (!bound) {
|
|
366
|
+
throw new Error(`Port ${port} is already in use (set useAvailablePortIfPortInUse to fall back to another port)`);
|
|
357
367
|
}
|
|
358
368
|
|
|
359
|
-
await listeningPromise;
|
|
360
369
|
port = (realServer.address() as net.AddressInfo).port;
|
|
361
370
|
|
|
362
371
|
if (config.autoForwardPort && config.public) {
|