Files
hmmmm/inc/proto/msg.h
root 589bc8d620 feat: migrate config management from TOML to FlatBuffers
Config is now loaded at runtime via WebSocket (ConfigCtrlMessage)
instead of from hardcoded TOML files. The emulator starts with no
devices and waits for clients to send configuration.

- Define FlatBuffers schemas: EmulationConfig, ComposeDeviceConfig,
  BaseDeviceConfig with recursive DeviceConfig union
- Rename MemSegment.start → addr (flatcc builder/reader name collision)
- Add ConfigCtrlMessage handler: validates STILL state, walks the
  device tree depth-first, assigns numeric IDs, responds with
  DeviceIdMappingNotif or ConfigLoadError
- Add fb_build_config_device_id_mapping() and fb_build_config_error()
  FlatBuffer builders
- Remove hardcoded device loading from main.c; iterate dynamically
  loaded devices in the exec loop
- Fix double-free: freeConf() already frees the struct itself, remove
  redundant free() calls in config.c and base_device.c
- Fix heap-buffer-overflow in device parseSpecsFromConfig: malloc
  for segment name was missing +1 for the null terminator

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-31 14:02:41 +00:00

71 lines
2.7 KiB
C

#ifndef __PROTO_MSG_H__
#define __PROTO_MSG_H__
#include "wsServer/include/ws.h"
#include <stdint.h>
#include <stdlib.h>
#include "flatcc/flatcc_builder.h"
// Raw FlatBuffers frame copied from the WS thread, queued to the main loop.
typedef struct {
uint8_t* data;
size_t size;
} FbMessage;
typedef struct {
ws_cli_conn_t clientIdx;
uint8_t* msg;
size_t msgLen;
} OutgoingMessage;
// Build a ServerMessage{AuthResponse} frame. Returns a malloc'd buffer;
// ownership is transferred to the caller (dispatchOutgoingMessage will free it).
uint8_t* fb_build_auth_response(uint64_t nonce, uint64_t seat_id, size_t* len_out);
// Build a ServerMessage{CtrlServerMessage{ExecNotifyMessage}} frame.
uint8_t* fb_build_exec_notify(uint64_t nonce, uint64_t tclk, uint8_t state, size_t* len_out);
// Build a ServerMessage{StreamServerMessage{StreamDataPush}} frame.
// B must be a pre-initialized flatcc_builder_t; it is reset before use
// so the caller does not need to reset it manually between calls.
uint8_t* fb_build_stream_data_push(
flatcc_builder_t *B,
uint64_t nonce, uint32_t stream_id, uint64_t tclk,
const uint8_t* data, size_t data_len,
size_t* len_out);
// Build a ServerMessage{CtrlServerMessage{SetupBuf}} frame (echo back to client).
uint8_t* fb_build_setup_buf(uint64_t nonce, uint32_t lost_buf_size,
uint64_t client_lifetime_ticks, size_t* len_out);
// Build a ServerMessage{CtrlServerMessage{OrphanedResponse{entries=[]}}} frame.
uint8_t* fb_build_orphaned_response(uint64_t nonce, size_t* len_out);
// Build a ServerMessage{CtrlServerMessage{LostMessagesResponse{seat_id, messages=[]}}} frame.
uint8_t* fb_build_lost_messages_response(uint64_t nonce, uint64_t seat_id, size_t* len_out);
// Build a ServerMessage{MemServerMessage{MemReadResponse}} frame.
uint8_t* fb_build_mem_read_response(
uint64_t nonce, uint64_t tclk,
uint32_t device_id, uint32_t seg_id, uint32_t offset,
const uint8_t* data, size_t data_len,
size_t* len_out);
// Build a ServerMessage{StreamServerMessage{StreamRegConfirm}} frame.
uint8_t* fb_build_stream_reg_confirm(
uint64_t nonce, uint32_t stream_id,
uint32_t device_id, uint32_t seg_id, uint32_t offset, uint32_t length,
uint8_t mode, size_t* len_out);
// Build a ServerMessage{CtrlServerMessage{ConfigNotifMessage{DeviceIdMappingNotif}}} frame.
// paths: array of NULL-terminated string arrays; path_lens: component count per path.
uint8_t* fb_build_config_device_id_mapping(
uint64_t nonce,
char** paths[], size_t path_lens[],
size_t device_count, size_t* len_out);
// Build a ServerMessage{CtrlServerMessage{ConfigNotifMessage{ConfigLoadError}}} frame.
uint8_t* fb_build_config_error(uint64_t nonce, const char* message, size_t* len_out);
#endif // __PROTO_MSG_H__