// Package control exposes a local-only command channel into a running // gpu-turnstile service: a named pipe on Windows, a unix socket on Linux. // It lets unprivileged local users ask the service to do privileged work // that is safe to offer — currently triggering an update check, whose // payload is signature-verified regardless of who asks. The channel never // accepts data beyond a one-word command, and the server rate-limits // triggers, so the worst a local user can cause is a cheap, throttled // check and a GPU-idle-gated restart onto a signed binary. // // Protocol: the client writes one command line, the server answers with // one reply line ("OK ..." or "ERR ...") and hangs up. package control import ( "bufio" "errors" "fmt" "io" "strings" ) // CmdUpdateNow asks the service to check for, stage and (once the GPU is // idle) restart onto a signed update immediately. const CmdUpdateNow = "update-now" // ErrUnavailable means no running service offers the control channel. var ErrUnavailable = errors.New("control channel unavailable") // Handler answers one command; the returned string is sent back as one // line. It must start with "OK " or "ERR ". type Handler func(cmd string) string // serveConn runs the line protocol on one accepted connection. func serveConn(c io.ReadWriteCloser, h Handler) { defer c.Close() line, err := bufio.NewReader(io.LimitReader(c, 4096)).ReadString('\n') cmd := strings.TrimSpace(line) if cmd == "" { if err != nil { return } fmt.Fprintln(c, "ERR empty command") return } fmt.Fprintln(c, h(cmd)) } // readReply writes cmd and reads the server's one-line reply. func readReply(c io.ReadWriteCloser, cmd string) (string, error) { if _, err := fmt.Fprintln(c, cmd); err != nil { return "", err } // The server hangs up after its reply; a broken-pipe error after the // last byte still leaves the reply in the buffer. data, _ := io.ReadAll(io.LimitReader(c, 4096)) line := strings.TrimSpace(string(data)) if line == "" { return "", ErrUnavailable } return line, nil }