Sends 6-byte framed announcements to 224.0.0.251:5353 on startup and
every interval_ms (default 5s). Receive thread maintains a peer table
(max 64 entries); fires on_peer_found for new peers, on_peer_lost when
a peer misses timeout_intervals (default 3) consecutive intervals.
Own announcements are filtered by name+site_id. SO_REUSEADDR+REUSEPORT
allows multiple processes on the same host for testing.
discovery_cli: announce <name> <tcp_port> [flags] — prints found/lost events.
Also notes future config module in planning.md.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Removes channel_id from the header. All message-specific identifiers
(stream_id, request_id, etc.) now live at the start of the payload,
interpreted by each message type handler. A relay seeing an unknown
type can skip or forward it using only payload_length, with no
knowledge of the payload structure.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
transport_server_create/start: binds TCP, spawns accept thread, closes
excess inbound connections when max_connections is reached.
transport_connect: outbound TCP, spawns read thread before returning.
transport_send_frame: packs 8-byte header with serial put_*, then writes
header + payload under a per-connection mutex (thread-safe).
Read thread: reads header, validates payload_length <= max_payload, mallocs
payload, calls on_frame (callback owns and must free payload). On error or
disconnect calls on_disconnect then frees conn.
transport_cli: server mode echoes received frames; client mode sends 3
test frames and prints echoes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
put_u8/16/32/64 and get_u8/16/32/64 (plus signed variants) for packing
and unpacking values at explicit byte offsets in a buffer. Each value is
encoded byte-by-byte with explicit shift operations — no struct casting,
no alignment assumptions, correct on any host endianness.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The CLI is a separate translation unit that doesn't include <linux/media.h>,
so the kernel flag constants were undefined there. Fix by defining our own
public constants in media_ctrl.h:
- MEDIA_LINK_FL_{ENABLED,IMMUTABLE,DYNAMIC} for link flags
- MEDIA_PAD_FLAG_{SINK,SOURCE} for pad flags (distinct names avoid
redefinition conflict with kernel's MEDIA_PAD_FL_* in media_ctrl.c)
media_ctrl.c now translates kernel flags to our constants on the way out.
Added fallback #defines for kernel constants that were missing them.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Modules (src/modules/):
- common/error: App_Error struct with structured detail union, error codes,
app_error_print(); designed for future upgrade to preprocessor-generated
location codes
- media_ctrl: media device enumeration, topology query (entities/pads/links),
link enable/disable via Media Controller API (/dev/media*)
- v4l2_ctrl: control enumeration (with menu item fetching), get/set via
V4L2 ext controls API, device discovery (/dev/video*)
All modules use -std=c11 -D_GNU_SOURCE, build artifacts go to build/ only.
Kernel-version-dependent constants guarded with #ifdef + #warning.
CLI drivers (dev/cli/):
- media_ctrl_cli: list, info, topology, set-link subcommands
- v4l2_ctrl_cli: list, controls, get, set subcommands
Docs (docs/cli/):
- media_ctrl_cli.md and v4l2_ctrl_cli.md with usage, examples, and
context within the video routing system
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>