change around pings, fix main.js so the actual real fucking number shows instead of it freaking out.

This commit is contained in:
KingKDot
2026-07-09 13:55:36 -05:00
parent f96b3d0721
commit 43ee5a7d4b
12 changed files with 293 additions and 32 deletions
@@ -0,0 +1,47 @@
import { describe, expect, test } from "bun:test";
import { decodeMessage } from "../../protocol";
import type { ClientInfo } from "../../types";
import { dispatchPingBulk } from "./client-command-routes";
function makeClient(): ClientInfo {
const sent: Uint8Array[] = [];
return {
id: "bulk-ping-client",
role: "client",
lastSeen: Date.now(),
ws: {
send(data: Uint8Array) {
sent.push(data);
},
_sent: sent,
},
} as any;
}
describe("client command ping diagnostics", () => {
test("dispatchPingBulk sends the requested number of pings", () => {
const client = makeClient();
const sent = (client.ws as any)._sent as Uint8Array[];
const count = dispatchPingBulk(client, 3);
expect(count).toBe(3);
expect(sent.length).toBe(3);
for (const raw of sent) {
const payload = decodeMessage(raw) as any;
expect(payload.type).toBe("ping");
expect(typeof payload.ts).toBe("number");
}
expect(typeof client.lastPingNonce).toBe("number");
});
test("dispatchPingBulk clamps invalid and large counts", () => {
const invalid = makeClient();
expect(dispatchPingBulk(invalid, "bad")).toBe(1);
expect((invalid.ws as any)._sent.length).toBe(1);
const large = makeClient();
expect(dispatchPingBulk(large, 5000)).toBe(1000);
expect((large.ws as any)._sent.length).toBe(1000);
});
});
@@ -7,6 +7,8 @@ import { metrics } from "../../metrics";
import { encodeMessage } from "../../protocol";
import { requireClientAccess, requireFeatureAccess, requirePermission } from "../../rbac";
import { clearThumbnail } from "../../thumbnails";
import type { ClientInfo } from "../../types";
import { sendPingRequest } from "../../wsHandlers";
type RequestIpProvider = {
requestIP: (req: Request) => { address?: string } | null | undefined;
@@ -32,6 +34,20 @@ type ClientCommandDeps = {
pendingCommandReplies: Map<string, PendingCommandReply>;
};
function clampPositiveInt(value: unknown, fallback: number, max: number): number {
const parsed = Number(value);
if (!Number.isFinite(parsed) || parsed <= 0) return fallback;
return Math.min(max, Math.max(1, Math.floor(parsed)));
}
export function dispatchPingBulk(target: ClientInfo, countValue: unknown): number {
const count = clampPositiveInt(countValue, 1, 1000);
for (let i = 0; i < count; i++) {
sendPingRequest(target, target.ws, "manual-bulk", 0);
}
return count;
}
export async function handleClientCommandRoute(
req: Request,
url: URL,
@@ -71,12 +87,13 @@ export async function handleClientCommandRoute(
let success = true;
if (action === "ping") {
const nonce = Date.now() + Math.floor(Math.random() * 1000);
target.lastPingSent = Date.now();
target.lastPingNonce = nonce;
target.ws.send(encodeMessage({ type: "ping", ts: nonce }));
sendPingRequest(target, target.ws, "manual", 0);
metrics.recordCommand("ping");
} else if (action === "ping_bulk") {
Math.max(1, Math.min(1000, Number(body?.count || 1)));
const count = dispatchPingBulk(target, body?.count);
metrics.recordCommand("ping_bulk");
logAudit({ timestamp: Date.now(), username: user.username, ip, action: AuditAction.COMMAND, targetClientId: targetId, details: `ping_bulk:${count}`, success: true });
return Response.json({ ok: true, sent: count }, { headers: deps.CORS_HEADERS });
} else if (action === "disconnect") {
try {
requirePermission(user, "clients:disconnect");