Refactor Tunnel
This commit is contained in:
@@ -7,15 +7,14 @@ import {
|
||||
enableTunnel, enableTailscale,
|
||||
isTunnelManuallyDisabled, isTunnelReconnecting, isTailscaleReconnecting,
|
||||
getTunnelService, getTailscaleService, setTunnelUnexpectedExitCallback,
|
||||
} from "@/lib/tunnel/tunnelManager";
|
||||
import { killCloudflared, isCloudflaredRunning, ensureCloudflared } from "@/lib/tunnel/cloudflared";
|
||||
import { isTailscaleRunning } from "@/lib/tunnel/tailscale";
|
||||
import { loadState } from "@/lib/tunnel/state";
|
||||
import { checkInternet, probeUrlAlive } from "@/lib/tunnel/networkProbe";
|
||||
import {
|
||||
killCloudflared, isCloudflaredRunning, ensureCloudflared,
|
||||
isTailscaleRunning,
|
||||
loadState,
|
||||
checkInternet,
|
||||
probeCloudflareAlive, probeTailscaleAlive,
|
||||
RESTART_COOLDOWN_MS, NETWORK_SETTLE_MS,
|
||||
WATCHDOG_INTERVAL_MS, NETWORK_CHECK_INTERVAL_MS,
|
||||
} from "@/lib/tunnel/tunnelConfig";
|
||||
} from "@/lib/tunnel";
|
||||
import { getMitmStatus, startMitm, loadEncryptedPassword, initDbHooks, restoreToolDNS, removeAllDNSEntriesSync } from "@/mitm/manager";
|
||||
import { syncToJson as syncMitmAliasCache } from "@/lib/mitmAliasCache";
|
||||
|
||||
@@ -130,6 +129,10 @@ async function autoStartMitm() {
|
||||
}
|
||||
}
|
||||
|
||||
// Cooldown only applies to repeating watchdog ticks (anti hammer-loop).
|
||||
// Network/exit events are one-shot transitions → bypass to recover fast.
|
||||
const FORCE_RESTART_REASONS = /^(startup|netchange|sleep|sleep\+netchange|online|unexpected-exit)$/;
|
||||
|
||||
// ─── Safe restart (4 guards: spawn / cooldown / alive / internet) ────────────
|
||||
|
||||
async function safeRestartTunnel(reason) {
|
||||
@@ -138,27 +141,33 @@ async function safeRestartTunnel(reason) {
|
||||
if (!settings.tunnelEnabled) return;
|
||||
if (svc.cancelToken.cancelled) return;
|
||||
if (svc.spawnInProgress) return;
|
||||
// Bypass cooldown when process is dead (real respawn, not restart-loop guard)
|
||||
const processDead = !isCloudflaredRunning();
|
||||
if (!processDead && Date.now() - svc.lastRestartAt < RESTART_COOLDOWN_MS) return;
|
||||
|
||||
// Alive check: process up + BOTH direct & public URL respond → skip
|
||||
// Alive check FIRST: probe URLs to decide health (process up but tunnel 530 = dead)
|
||||
let alive = false;
|
||||
if (isCloudflaredRunning()) {
|
||||
const state = loadState();
|
||||
const publicUrl = state?.shortId ? `https://r${state.shortId}.abc-tunnel.us` : null;
|
||||
const directUrl = state?.tunnelUrl || null;
|
||||
if (publicUrl && directUrl) {
|
||||
const [publicOk, directOk] = await Promise.all([
|
||||
probeUrlAlive(publicUrl),
|
||||
probeUrlAlive(directUrl),
|
||||
probeCloudflareAlive(publicUrl),
|
||||
probeCloudflareAlive(directUrl),
|
||||
]);
|
||||
if (publicOk && directOk) return;
|
||||
alive = publicOk && directOk;
|
||||
}
|
||||
}
|
||||
if (alive) return;
|
||||
|
||||
// Degraded/dead → cooldown only prevents hammer loop after a recent restart attempt.
|
||||
// Bypass for network transitions (one-shot events) so user recovers fast after wifi change.
|
||||
const force = FORCE_RESTART_REASONS.test(reason);
|
||||
if (!force && Date.now() - svc.lastRestartAt < RESTART_COOLDOWN_MS) {
|
||||
console.log(`[Tunnel] degraded but cooldown active, skip (${reason})`);
|
||||
return;
|
||||
}
|
||||
if (!await checkInternet()) return;
|
||||
|
||||
console.log(`[Tunnel] safeRestart (${reason})`);
|
||||
console.log(`[Tunnel] safeRestart (${reason}) — tunnel unreachable${force ? " [force]" : ""}`);
|
||||
try {
|
||||
await enableTunnel();
|
||||
svc.lastRestartAt = Date.now();
|
||||
@@ -174,15 +183,22 @@ async function safeRestartTailscale(reason) {
|
||||
if (!settings.tailscaleEnabled) return;
|
||||
if (svc.cancelToken.cancelled) return;
|
||||
if (svc.spawnInProgress) return;
|
||||
if (Date.now() - svc.lastRestartAt < RESTART_COOLDOWN_MS) return;
|
||||
|
||||
// Alive check FIRST: daemon up + URL responds = healthy
|
||||
let alive = false;
|
||||
if (isTailscaleRunning() && settings.tailscaleUrl) {
|
||||
if (await probeUrlAlive(settings.tailscaleUrl)) return;
|
||||
alive = await probeTailscaleAlive(settings.tailscaleUrl);
|
||||
}
|
||||
if (alive) return;
|
||||
|
||||
const force = FORCE_RESTART_REASONS.test(reason);
|
||||
if (!force && Date.now() - svc.lastRestartAt < RESTART_COOLDOWN_MS) {
|
||||
console.log(`[Tailscale] degraded but cooldown active, skip (${reason})`);
|
||||
return;
|
||||
}
|
||||
if (!await checkInternet()) return;
|
||||
|
||||
console.log(`[Tailscale] safeRestart (${reason})`);
|
||||
console.log(`[Tailscale] safeRestart (${reason}) — tunnel unreachable${force ? " [force]" : ""}`);
|
||||
try {
|
||||
await enableTailscale();
|
||||
svc.lastRestartAt = Date.now();
|
||||
|
||||
Reference in New Issue
Block a user