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>
71 lines
2.7 KiB
C
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__
|