import assert from "node:assert/strict"; import { describe, it } from "node:test"; import { buildNetworkPortrait, classifyCandidateAddress, createPendingNetworkDiagnostics, parseIceCandidateLine, redactNetworkDiagnosticsForRecording, summarizeIceCandidatesForRecording, } from "../src/network.mjs"; describe("network diagnostics", () => { it("parses and classifies common WebRTC ICE candidate address forms", () => { const host = parseIceCandidateLine( "candidate:842163049 1 udp 1677729535 192.168.1.5 54400 typ host generation 0 ufrag abc network-cost 999", ); assert.equal(host.address, "192.168.1.5"); assert.equal(host.type, "host"); assert.equal(host.category, "private"); const mdns = parseIceCandidateLine("candidate:1 1 udp 2122252543 a1b2c3d4.local 5353 typ host"); assert.equal(mdns.address, "a1b2c3d4.local"); assert.equal(mdns.category, "mdns"); const reflexive = parseIceCandidateLine( "candidate:2 1 udp 1686052607 203.0.113.10 60000 typ srflx raddr 0.0.0.0 rport 9", ); assert.equal(reflexive.address, "203.0.113.10"); assert.equal(reflexive.type, "srflx"); assert.equal(reflexive.category, "public"); assert.equal(classifyCandidateAddress("fd00::1"), "private"); assert.equal(classifyCandidateAddress("2001:4860:4860::8888"), "public"); }); it("summarizes WebRTC data without retaining exact network addresses", () => { const candidates = [ parseIceCandidateLine( "candidate:842163049 1 udp 1677729535 192.168.1.5 54400 typ host generation 0", ), parseIceCandidateLine("candidate:1 1 udp 2122252543 a1b2c3d4.local 5353 typ host"), parseIceCandidateLine("candidate:2 1 udp 1686052607 203.0.113.10 60000 typ srflx"), ]; const summary = summarizeIceCandidatesForRecording(candidates); assert.deepEqual(summary, { total: 3, public: 1, private: 1, mdns: 1, masked: 0, host: 2, srflx: 1, relay: 0, prflx: 0, }); const signals = redactNetworkDiagnosticsForRecording({ webrtc: { candidates }, server: { observedIp: "198.51.100.24", forwardedFor: "203.0.113.42", cfConnectingIp: null, realIpHeader: null, }, connection: { effectiveType: "4g", downlink: 10, rtt: 40, saveData: false }, }); const raw = signals.map((signal) => signal.raw).join(" "); assert.equal(signals.every((signal) => signal.raw.length <= 160), true); assert.match(raw, /webrtc total=3 public=1 private=1 mdns=1/); assert.match(raw, /server observed=1 forwarded=1 cf=0 real=0/); assert.doesNotMatch(raw, /\b(?:\d{1,3}\.){3}\d{1,3}\b/); assert.doesNotMatch(raw, /a1b2c3d4\.local/); }); it("builds an explainable network portrait from server and WebRTC evidence", () => { const portrait = buildNetworkPortrait( { status: "done", server: { observedIp: "198.51.100.24", forwardedFor: "203.0.113.42", cfConnectingIp: "198.51.100.24", cfIpCountry: "US", geoIp: { city: { available: true, found: true, countryCode: "US", region: "California", city: "Los Angeles", latitude: 34.05, longitude: -118.24, timeZone: "America/Los_Angeles", accuracyRadiusKm: 20, }, asn: { available: true, found: true, asn: 15169, organization: "Google LLC", isp: "Google LLC", }, }, }, webrtc: { summary: { total: 3, public: 1, private: 1, mdns: 1, srflx: 1 } }, connection: { supported: true, effectiveType: "4g", rtt: 40, downlink: 10, saveData: false }, }, [ { id: "timezone", label: "系统时区", value: "America/Los_Angeles" }, { id: "language", label: "浏览器语言", value: "en-US, zh-CN" }, ], ); assert.equal(portrait.level, "high"); assert.ok(portrait.confidence >= 80); assert.match(portrait.headline, /网络出口/); assert.equal(portrait.rows.some((row) => row.label === "Cloudflare 国家"), true); assert.equal(portrait.rows.some((row) => row.label === "IP 数据库位置" && row.value.includes("Los Angeles")), true); assert.equal(portrait.rows.some((row) => row.label === "ASN / ISP" && row.value.includes("Google LLC")), true); assert.equal(portrait.rows.some((row) => row.label === "WebRTC 暴露"), true); assert.equal(portrait.evidence.some((item) => item.includes("America/Los_Angeles")), true); assert.equal(portrait.limitations.some((item) => item.includes("不能等同于精确住址")), true); }); it("can expose server diagnostics while WebRTC is still collecting", () => { const diagnostics = createPendingNetworkDiagnostics({ observedIp: "127.0.0.1", geoIp: { city: { available: true, found: false }, asn: { available: true, found: false }, }, }); assert.equal(diagnostics.status, "done"); assert.equal(diagnostics.server.observedIp, "127.0.0.1"); assert.equal(diagnostics.webrtc.pending, true); assert.equal(diagnostics.webrtc.summary.total, 0); assert.equal(diagnostics.connection.supported, false); }); });