Refactor Tunnel
This commit is contained in:
1 parent
96a9a2b36d
commit
b876e0225a
35 files changed
+642
-574
No files matched your search
@@ -0,0 +1,17 @@
|
||||
import dns from "dns";
|
||||
|
||||
// Force public DNS to bypass OS negative cache (mDNSResponder holds NXDOMAIN)
|
||||
const resolver = new dns.promises.Resolver();
|
||||
resolver.setServers(["1.1.1.1", "1.0.0.1", "8.8.8.8"]);
|
||||
|
||||
// Try custom public DNS first, fall back to OS resolver
|
||||
// (Cloudflare DNS may not resolve all hostnames, e.g. *.ts.net)
|
||||
export async function resolveDns(hostname, timeoutMs) {
|
||||
const tryResolver = (fn) => Promise.race([
|
||||
fn(),
|
||||
new Promise((_, rej) => setTimeout(() => rej(new Error("dns timeout")), timeoutMs)),
|
||||
]).then(() => true).catch(() => false);
|
||||
|
||||
if (await tryResolver(() => resolver.resolve4(hostname))) return true;
|
||||
return tryResolver(() => dns.promises.resolve4(hostname));
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import net from "net";
|
||||
|
||||
const INTERNET_CHECK = {
|
||||
host: "1.1.1.1",
|
||||
port: 443,
|
||||
timeoutMs: 3000,
|
||||
};
|
||||
|
||||
export function checkInternet() {
|
||||
return new Promise((resolve) => {
|
||||
const socket = new net.Socket();
|
||||
let done = false;
|
||||
const finish = (ok) => {
|
||||
if (done) return;
|
||||
done = true;
|
||||
try { socket.destroy(); } catch { /* ignore */ }
|
||||
resolve(ok);
|
||||
};
|
||||
socket.setTimeout(INTERNET_CHECK.timeoutMs);
|
||||
socket.once("connect", () => finish(true));
|
||||
socket.once("timeout", () => finish(false));
|
||||
socket.once("error", () => finish(false));
|
||||
try { socket.connect(INTERNET_CHECK.port, INTERNET_CHECK.host); }
|
||||
catch { finish(false); }
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { DATA_DIR } from "@/lib/dataDir.js";
|
||||
|
||||
const TUNNEL_DIR = path.join(DATA_DIR, "tunnel");
|
||||
const STATE_FILE = path.join(TUNNEL_DIR, "state.json");
|
||||
|
||||
const SHORT_ID_LENGTH = 6;
|
||||
const SHORT_ID_CHARS = "abcdefghijklmnpqrstuvwxyz23456789";
|
||||
|
||||
export function ensureTunnelDir() {
|
||||
if (!fs.existsSync(TUNNEL_DIR)) fs.mkdirSync(TUNNEL_DIR, { recursive: true });
|
||||
}
|
||||
|
||||
export function loadState() {
|
||||
try {
|
||||
if (fs.existsSync(STATE_FILE)) return JSON.parse(fs.readFileSync(STATE_FILE, "utf8"));
|
||||
} catch { /* ignore corrupt state */ }
|
||||
return null;
|
||||
}
|
||||
|
||||
export function saveState(state) {
|
||||
ensureTunnelDir();
|
||||
fs.writeFileSync(STATE_FILE, JSON.stringify(state, null, 2));
|
||||
}
|
||||
|
||||
export function clearState() {
|
||||
try {
|
||||
if (fs.existsSync(STATE_FILE)) fs.unlinkSync(STATE_FILE);
|
||||
} catch { /* ignore */ }
|
||||
}
|
||||
|
||||
export function generateShortId() {
|
||||
let result = "";
|
||||
for (let i = 0; i < SHORT_ID_LENGTH; i++) {
|
||||
result += SHORT_ID_CHARS.charAt(Math.floor(Math.random() * SHORT_ID_CHARS.length));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export { TUNNEL_DIR };
|
||||
@@ -0,0 +1,5 @@
|
||||
// Watchdog + network monitor timings (shared by both services)
|
||||
export const RESTART_COOLDOWN_MS = 120000;
|
||||
export const NETWORK_SETTLE_MS = 2500;
|
||||
export const WATCHDOG_INTERVAL_MS = 60000;
|
||||
export const NETWORK_CHECK_INTERVAL_MS = 5000;
|
||||
Reference in new issue
Block a user