zm::UnixSocket copies the path with a truncating strncpy, so a
PATH_SOCKS long enough to overflow sun_path made the server bind one
file while chmod, chown and unlink acted on another, and the client
connect to a truncated, different path. Both now refuse such a path with
an error. Start() also closes the listener on its own failure paths.
SendMedia indexed the two-entry sequence array with the stream id; a
caller passing StreamId::Monitor would have written past it. Ignore
anything that is not video or audio.
Tests: server and client refuse a 200 character path; a Monitor stream
id is ignored and does not disturb the video sequence.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Address several stream socket review findings on the transport, its
consumer client and the wire protocol:
- ParseAllowedUids rejects negative, out-of-range and non-round-tripping
uids instead of wrapping or truncating them (e.g. 2^32 no longer
becomes uid 0).
- StreamSocketClient backs off after a connection the producer closes
before any message, so a rejected consumer (uid allow-list, client
limit) no longer busy-loops; a rejection is not reported as a
disconnect.
- SendMedia drops packets for a stream that has no announced HELLO, and
ClearAudioParams forgets a previously announced audio stream (bumping
the generation and re-issuing the surviving video HELLO), so a stale
audio HELLO is never replayed and media never precedes its HELLO.
- Header pts_us is encoded as signed (two's-complement) microseconds so
negative and AV_NOPTS_VALUE timestamps survive the wire; the dump tool
decodes it as signed and tracks sequence gaps per generation so a
generation reset is not mistaken for packet loss.
Tests cover the uid rejections, the audio HELLO clearing and media
guard, the connection-rejection backoff, and signed pts round-trips.
refs #5143
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T4UcdJLt1bxwdpcigGxZRD
Both suites bound a fixed path under /tmp, so two test binaries running
at once (parallel ctest, a developer and CI on one box) would unlink
each other's listener. Include the pid in the path.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The consumer class dispatched HELLO, MEDIA, KEYFRAME, STATS and BYE but
had no case for the EVENT type added for the monitor lifecycle channel,
so every event fell into the unknown-type branch and was dropped at
debug level 2. Add an on_event callback that receives the parsed
MonitorEvent together with the header (event sequence and media
generation), and reject malformed payloads with a warning like HELLO.
Tests: a client connected to a StreamSocket receives the cached snapshot
on connect and a broadcast state_changed, with the codes, state names,
health code, message and wall clock intact.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Reader side of the stream socket protocol, for zm_rtsp_server and any
in-tree consumer: connects to PATH_SOCKS/stream_{id}.sock with 1s retry,
reads exact-size length-prefixed messages into one reused buffer (no
per-read allocation churn, no resync scanning - contrast the FIFO
reader's 4KB chunking and memmem hunting), validates headers and
dispatches HELLO/MEDIA/KEYFRAME/STATS/BYE through callbacks on the
reader thread. Reconnects automatically on EOF or protocol error; a
fresh HELLO arrives after every reconnect. An adopt-fd constructor
supports tests and single-shot uses.
Tests: 5 new Catch2 cases - end-to-end against a real StreamSocket
(HELLO fields, media payload integrity), BYE + reconnect across a
server restart, fragmented byte-stream delivery via socketpair,
malformed-header disconnect, unknown-message-type skip. Full suite:
103/103 pass via ctest.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>