@@ -6,6 +6,30 @@ type TailscaleSelfInfo = {
|
6 | 6 | nodeId: string | null; |
7 | 7 | }; |
8 | 8 | |
| 9 | +export const TAILSCALE_COMMAND_STDOUT_MAX_BYTES = 4 * 1024 * 1024; |
| 10 | + |
| 11 | +type TailscaleCommandStdout = { |
| 12 | +bytes: number; |
| 13 | +exceeded: boolean; |
| 14 | +text: string; |
| 15 | +}; |
| 16 | + |
| 17 | +export function appendTailscaleCommandStdout( |
| 18 | +current: TailscaleCommandStdout, |
| 19 | +data: Buffer | string, |
| 20 | +maxBytes = TAILSCALE_COMMAND_STDOUT_MAX_BYTES, |
| 21 | +): TailscaleCommandStdout { |
| 22 | +if (current.exceeded) { |
| 23 | +return current; |
| 24 | +} |
| 25 | +const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data); |
| 26 | +const bytes = current.bytes + buffer.byteLength; |
| 27 | +if (bytes > maxBytes) { |
| 28 | +return { bytes, exceeded: true, text: "" }; |
| 29 | +} |
| 30 | +return { bytes, exceeded: false, text: `${current.text}${buffer.toString("utf8")}` }; |
| 31 | +} |
| 32 | + |
9 | 33 | function runTailscaleCommand( |
10 | 34 | args: string[], |
11 | 35 | timeoutMs = 2500, |
@@ -15,7 +39,7 @@ function runTailscaleCommand(
|
15 | 39 | stdio: ["ignore", "pipe", "pipe"], |
16 | 40 | }); |
17 | 41 | |
18 | | -let stdout = ""; |
| 42 | +let stdout: TailscaleCommandStdout = { bytes: 0, exceeded: false, text: "" }; |
19 | 43 | let settled = false; |
20 | 44 | let timer: ReturnType<typeof setTimeout>; |
21 | 45 | const finish = (result: { code: number; stdout: string }) => { |
@@ -28,7 +52,11 @@ function runTailscaleCommand(
|
28 | 52 | }; |
29 | 53 | |
30 | 54 | proc.stdout.on("data", (data) => { |
31 | | -stdout += data; |
| 55 | +stdout = appendTailscaleCommandStdout(stdout, data); |
| 56 | +if (stdout.exceeded) { |
| 57 | +proc.kill("SIGKILL"); |
| 58 | +finish({ code: -1, stdout: "" }); |
| 59 | +} |
32 | 60 | }); |
33 | 61 | |
34 | 62 | timer = setTimeout(() => { |
@@ -41,13 +69,13 @@ function runTailscaleCommand(
|
41 | 69 | }); |
42 | 70 | |
43 | 71 | proc.on("close", (code) => { |
44 | | -finish({ code: code ?? -1, stdout }); |
| 72 | +finish({ code: code ?? -1, stdout: stdout.text }); |
45 | 73 | }); |
46 | 74 | }); |
47 | 75 | } |
48 | 76 | |
49 | 77 | export async function getTailscaleSelfInfo(): Promise<TailscaleSelfInfo | null> { |
50 | | -const { code, stdout } = await runTailscaleCommand(["status", "--json"]); |
| 78 | +const { code, stdout } = await runTailscaleCommand(["status", "--json", "--peers=false"]); |
51 | 79 | if (code !== 0) { |
52 | 80 | return null; |
53 | 81 | } |
|