feedback7 G-TOOLS: listen on :: by default so one socket serves IPv6 and IPv4 (PR #291 by @LimitlessHPPK)

Ported only the dual-stack listen from PR #291 (the change accepted as #188). With HOST unset the server binds :: and, if that fails with EAFNOSUPPORT, EADDRNOTAVAIL or EINVAL, retries 0.0.0.0. An explicit HOST, including 0.0.0.0 and 127.0.0.1, is tried once. The boot banner and doctor list shareable IPv6 addresses in brackets, skip fe80::, and keep one URL per /64. An explicit IPv6 literal in the local URL is bracketed. The Windows service listing no longer drops those bracketed lines.

Not ported: /dev/grant, the settings-default migration, and the firewall scripts. The Docker image stays on 0.0.0.0; the alpine fallback was not booted.

Tests: node --test test/ipv6-bind.test.js test/doctor.test.js test/ci.test.js — 20 pass, 0 fail (8 bind, 4 doctor, 8 ci).
This commit is contained in:
LimitlessHPPK authored and sganggs committed 2026-10-08 18:53:24 +08:00
1 parent c36320fe4a
commit 51c53de189
11 files changed
+374 -54

No files matched your search

+5 -3
View File
@@ -13,7 +13,7 @@
#>
param(
[int]$Port = 3000,
[string]$BindHost = '0.0.0.0',
[string]$BindHost = '::',
[ValidateSet('client', 'server')][string]$Combat = 'client',
[ValidateSet('off', 'sample', 'all')][string]$Verify = 'off',
[string]$TaskName = 'StrongholdProtocol',
@@ -162,8 +162,10 @@ try {
Start-ScheduledTask -TaskName $TaskName -ErrorAction Stop
Start-Sleep -Seconds 4
Show-Status
Write-Host "`n朋友访问地址(局域网):"
& $nodeExe tools\doctor.mjs --port $Port | Select-String -Pattern 'http://\d' | ForEach-Object { Write-Host " $($_.Line.Trim())" }
Write-Host "`n朋友访问地址(局域网 / IPv6,方括号不能少):"
# doctor prints a full URL. An IPv6 literal is bracketed, so a pattern that requires a digit right after http://
# would drop it. Keep every http:// line; the rest of the report is classification text.
& $nodeExe tools\doctor.mjs --port $Port | Select-String -Pattern 'http://' | ForEach-Object { Write-Host " $($_.Line.Trim())" }
Write-Host "`n停止:-Stop 重启:-Restart 状态:-Status 卸载:-Uninstall 日志:$Log"
} catch {
Write-Host "`n出错:$($_.Exception.Message)" -ForegroundColor Red
+5 -5
View File
@@ -2,7 +2,7 @@
// scripts/launch.mjs — cross-platform "prepare + start + open the browser", used by scripts/start-windows.bat,
// scripts/start-windows.ps1 and scripts/start.sh (docs/DEPLOY.md).
//
// node scripts/launch.mjs [--port 3000] [--host 0.0.0.0] [--no-open] [--no-setup] [setup options…]
// node scripts/launch.mjs [--port 3000] [--host ::] [--no-open] [--no-setup] [setup options…]
//
// 1. If our server already answers on the port, just open the browser (double-clicking twice is harmless).
// 2. An update package extracted over the folder (UPDATE.json) is finished (server/update.js; the server does it too,
@@ -30,11 +30,11 @@ if (Number(process.versions.node.split('.')[0]) < 22) {
}
const { c, mark } = await import('../tools/setup.mjs');
const { probePort, classifyAddresses, KIND_LABEL } = await import('../tools/doctor.mjs');
const { probePort, classifyAddresses, hostUrl, KIND_LABEL } = await import('../tools/doctor.mjs');
const { applyPendingUpdate, UPDATE_FILE } = await import('../server/update.js');
function parseArgs(argv) {
const o = { port: Number(process.env.PORT) || 3000, host: process.env.HOST || '0.0.0.0', open: !/^(1|true|yes)$/i.test(process.env.SP_NO_BROWSER || ''), setup: true, setupArgs: [], help: false };
const o = { port: Number(process.env.PORT) || 3000, host: process.env.HOST || '::', open: !/^(1|true|yes)$/i.test(process.env.SP_NO_BROWSER || ''), setup: true, setupArgs: [], help: false };
for (let i = 0; i < argv.length; i++) {
const a = argv[i];
const [k, v] = a.split('=');
@@ -61,9 +61,9 @@ function printShare(port) {
console.log(`${mark.ok} ${c.bold('服务器已启动')} 本机打开:${c.cyan(`http://localhost:${port}`)}`);
if (addrs.length) {
console.log(' 发给朋友(需要能访问这台电脑的网络):');
for (const a of addrs.slice(0, 4)) console.log(` ${c.cyan(`http://${a.address}:${port}`)} ${c.dim(KIND_LABEL[a.kind])}`);
for (const a of addrs.slice(0, 4)) console.log(` ${c.cyan(hostUrl(a.address, port))} ${c.dim(KIND_LABEL[a.kind])}`);
} else {
console.log(c.warn(' 没有检测到局域网地址:朋友暂时无法连接(检查网线/Wi-Fi)。'));
console.log(c.warn(' 没有检测到可以分享的地址:朋友暂时无法连接(检查网线/Wi-Fi)。'));
}
console.log(c.dim(' 建房后把 4 位「同盟密钥」或「复制链接」(…/?room=密钥)发给朋友。'));
console.log(c.dim(' 朋友打不开?运行 node tools/doctor.mjs 检查防火墙。按 Ctrl+C 停止服务器。'));
+2
View File
@@ -5,6 +5,8 @@ rem Output goes to logs\server.log (rotated at 10 MB to logs\server.old.log); th
setlocal EnableExtensions
cd /d "%~dp0.."
set "NODE_EXE=node"
rem Dual-stack default (IPv6 and IPv4 on one socket). scripts\service.env.cmd may override HOST.
set "HOST=::"
if exist "%~dp0service.env.cmd" call "%~dp0service.env.cmd"
if not exist "logs" mkdir "logs"