// Sends the built payload to an ELF loader on the console. // // npm run payload:send -- 192.168.1.20 (loader on port 9021) // npm run payload:send -- 192.168.1.20 9020 import fs from 'node:fs'; import net from 'node:net'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; const [host, portArg] = process.argv.slice(2); if (!host) { console.error('Usage: npm run payload:send -- [loader port, default 9021]'); process.exit(1); } const port = Number(portArg ?? 9021); const elf = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../payload/cheatspecter.elf'); if (!fs.existsSync(elf)) { console.error('payload/cheatspecter.elf does not exist yet. Build it with: npm run payload'); process.exit(1); } const data = fs.readFileSync(elf); const sock = net.connect({ host, port, timeout: 5000 }); // Some loaders keep the connection open after taking the file, so once every // byte has gone out, a quiet connection is success, not a failure. let sent = false; let reported = false; const done = () => { if (reported) return; reported = true; console.log(`Sent ${(data.length / 1024).toFixed(0)} KB to ${host}:${port}. Watch the TV for the "CheatSpecter is ready" notification.`); }; sock.on('timeout', () => { if (sent) { done(); sock.destroy(); } else sock.destroy(new Error('timed out')); }); sock.on('connect', () => sock.end(data, () => (sent = true))); sock.on('close', (hadError) => { if (!hadError && sent) done(); }); sock.on('error', (err) => { if (reported) return; console.error(`Could not send to ${host}:${port} (${err.message}). Is an ELF loader running on the console?`); process.exitCode = 1; });