79 lines
include/ipc_dispatcher.h
Declares MessageHeader, Reply, error codes, and IpcDispatcher.
// IpcDispatcher: validates and routes messages from the Unix domain socket server.#pragma once#include <cstddef>#include <cstdint>#include <functional>#include <unordered_map>static constexpr uint32_t IPC_MAGIC = 0xD1C0FFEE;// Privilege-gated message types: only permitted when sender UID == 0.static constexpr uint16_t MSG_ADMIN_CONFIG = 0x10;static constexpr uint16_t MSG_SHUTDOWN = 0x11;static constexpr uint16_t STATUS_OK = 0;static constexpr uint16_t ERR_MAGIC = 1; // bad magic numberstatic constexpr uint16_t ERR_SHORT = 2; // buffer shorter than MessageHeaderstatic constexpr uint16_t ERR_PERM = 3; // caller lacks required privilegestatic constexpr uint16_t ERR_TYPE = 4; // unrecognised message type// Fixed-size message header; precedes the variable-length payload.// All fields are little-endian.struct MessageHeader { uint32_t magic; // must equal IPC_MAGIC; validated before any other field uint16_t totalLen; // total message length in bytes including this header uint16_t type; // message type determining handler and payload layout uint32_t senderUid; // UID claimed by the sender — not kernel-verified; do not use for auth uint32_t seq; // sequence number echoed in the reply for correlation};
// Fixed-size reply returned for every message.// sizeof(Reply) == 80 bytes; all 80 bytes are transmitted to the caller.struct Reply { uint16_t status; // ERR_* code or STATUS_OK uint16_t reserved; // must be zero uint32_t seq; // echoes MessageHeader::seq char payload[64]; // response data; only payloadLen bytes are meaningful uint16_t payloadLen; // number of valid bytes in payload[] char padding[6]; // alignment padding included in sizeof(Reply)};
// Handler function type for one message type.using HandlerFn = std::function<void(const uint8_t* payload, std::size_t payloadLen,Reply& reply)>;
// Dispatches validated messages to registered per-type handlers.class IpcDispatcher {public: IpcDispatcher(); // Registers a handler for the given message type. // Parameters: // msgType - the 16-bit message type to register // handler - callback invoked when a message of that type is dispatched // Returns: void void registerHandler(uint16_t msgType, HandlerFn handler); // Validates the incoming buffer and dispatches to the registered handler. // Parameters: // buf - raw bytes received from the socket // bufLen - number of bytes in buf // sockFd - socket file descriptor used to read peer credentials via SO_PEERCRED // reply - pre-allocated reply struct; must be fully initialised before sending // Returns: void; status code is written into reply.status void dispatch(const uint8_t* buf, std::size_t bufLen, int sockFd, Reply& reply);private: std::unordered_map<uint16_t, HandlerFn> handlers_; // per-type handler registry // Returns the UID of the connected peer via SO_PEERCRED. // Parameters: // sockFd - connected socket descriptor // Returns: peer UID, or static_cast<uint32_t>(-1) on error static uint32_t getPeerUid(int sockFd); // Parameters: // msgType - message type to test // Returns: true if the type requires root privilege static bool requiresPrivilege(uint16_t msgType);};