#ifndef UMBRELLA_PROTO_H #define UMBRELLA_PROTO_H #include /* * Wire format: 4-byte big-endian length prefix followed by a JSON payload. * * [uint32 length][JSON bytes...] * * All messages are JSON objects with at minimum a "cmd" or "type" field. * * Client → Daemon commands: * { "cmd": "list" } * { "cmd": "status", "unit": "name" } * { "cmd": "attach", "unit": "name" } * { "cmd": "detach" } * { "cmd": "input", "unit": "name", "data": "text\n" } * { "cmd": "action", "unit": "name", "action": "update" } * * Daemon → Client responses: * { "type": "ok" } * { "type": "error", "message": "..." } * { "type": "list", "units": [...] } * { "type": "status", "unit": "name", "state": "running", "pid": 123 } * { "type": "output", "unit": "name", "data": "...", "history": true/false } */ #define PROTO_HDR_SIZE 4 /* bytes for the length prefix */ /* * proto_send: send a length-prefixed JSON message to fd. * json must be a null-terminated string. * Returns 0 on success, -1 on error. */ int proto_send(int fd, const char *json); /* * proto_recv: receive one complete message from fd into buf. * buf must be PROTO_MAX_MSG bytes. * Returns number of bytes read (>=1), 0 on clean disconnect, -1 on error. */ int proto_recv(int fd, char *buf, int buf_size); /* * proto_send_ok: convenience — send {"type":"ok"} */ int proto_send_ok(int fd); /* * proto_send_error: convenience — send {"type":"error","message":"..."} */ int proto_send_error(int fd, const char *message); /* * proto_send_output: send a chunk of console output to a client. * history=1 means this is buffered history, 0 means live output. */ int proto_send_output(int fd, const char *unit_name, const char *data, int history); /* * json_get_str: extract a string value from a flat JSON object. * Writes into out (null-terminated), up to out_size bytes. * Returns 1 if found, 0 if not. * This is a minimal parser — does not handle nested objects or arrays. */ int json_get_str(const char *json, const char *key, char *out, int out_size); #endif /* UMBRELLA_PROTO_H */