diff --git a/server/src/network-observer.ts b/server/src/network-observer.ts index e83de9b..51722d9 100644 --- a/server/src/network-observer.ts +++ b/server/src/network-observer.ts @@ -109,7 +109,7 @@ function numericValue(line: string, name: string): number | null { async function flows(): Promise<{ available: boolean; flows: Flow[] }> { try { - const output = await execute("/usr/sbin/conntrack", ["--list"], 1024 * 1024); + const output = await execute("/usr/sbin/conntrack", ["-L"], 1024 * 1024); const parsed: Flow[] = []; for (const line of output.trim().split("\n")) { const protocol = line.match(/^(tcp|udp)\s/)?.[1] as "tcp" | "udp" | undefined; @@ -140,12 +140,16 @@ async function flows(): Promise<{ available: boolean; flows: Flow[] }> { async function collect(): Promise { const [clientList, dns, activeFlows] = await Promise.all([clients(), dnsQueries(), flows()]); + const activeClients = new Set(activeFlows.flows.map((flow) => flow.sourceAddress)); + const clientsWithFlowState = clientList.map((client) => + !client.connected && activeClients.has(client.ipAddress) ? { ...client, connected: true, state: "ACTIVE" } : client + ); const messages: string[] = []; if (!dns.available) messages.push("DNS query metadata is unavailable; restart the hotspot after installing its dnsmasq configuration."); if (!activeFlows.available) messages.push("Active flows are unavailable because conntrack is not installed or accessible."); return networkActivitySchema.parse({ collectedAt: new Date().toISOString(), - clients: clientList, + clients: clientsWithFlowState, dnsQueries: dns.queries, flows: activeFlows.flows, dnsAvailable: dns.available,