- hbc_mini.c: move the probe-thread pthread_join to after the shutdown HTB send,
so the clean-shutdown notification is no longer delayed behind (and possibly
lost to a SIGKILL racing) a probe thread blocked in popen()/ping.
- hbc_mini.c: log a LOGW when pthread_create() fails to start the probe thread,
and when probe_v4/probe_v6 are not IP literals (probe_init), so both previously
silent no-op failure modes are now diagnosable. Diagnostic only — no behavior
change to the PROBE_UNKNOWN fallback path.
- hbc_mini.py: remove the unused 'import struct' (F401).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uc9V1v7iXruubpoLiSE24M
Adds the pure/core probe logic for the standalone C client (hbc_mini.c):
gateway text parsers for /proc/net/route, /proc/net/ipv6_route and BSD
`route -n get`, a ping-output RTT parser, and the probe_step state machine
(probe_t/probe_fam_t/probe_ops_t) plus probe_flags and probe_metric_json.
config_t gains probe_enabled/probe_interval/probe_v4/probe_v6.
Temporary stub functions (sys_local_address, sys_ping, sys_gateway,
mono_ts) stand in for real syscalls until Task 4 wires them into main().
New scripts/c/test_probe.c test harness (#include's hbc_mini.c with main
renamed out of the way) plus a `make test` target; scripts/c/.gitignore
now ignores the test_probe binary.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uc9V1v7iXruubpoLiSE24M
CMD packets arrive as unauthenticated UDP datagrams, yet every hbc client
executed the shell command they carry without any opt-in. Add an
allow_remote_command config key, default false: when off, the command is
logged and refused with "Refused: allow_remote_command is false" (visible in
the server event log under the command service), and subprocess is never
reached. When on, the client warns at startup that it will execute CMD
packets.
Applied to all four clients that handle CMD — hbc, hbc_windows.py,
hbc_mini.py, and the C hbc_mini — since gating only one leaves the others
wide open. The C client reads the same key from ~/.hbc.json and needs a
rebuild to pick it up. UPD (self-update) is unchanged.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The server inferred each plugin's collection interval from the gap between
the last two received PLG samples, then expired data at interval * 3. After
an outage this guess was wrong: the request_update re-send of collect-once
InfoPlugins produced two close samples, yielding a tiny inferred interval
that purged permanent info data minutes after recovery.
Clients now declare each plugin's interval in the PLG message (_interval).
The server uses it directly (from the first post-recovery sample), expiring
at interval * 3 so live data survives at least two full intervals; interval
0 marks collect-once InfoPlugins that never go stale. Legacy clients omit
the field and fall back to the previous inferred-gap behavior.
Adds _interval to all three clients: hbc, hbc_mini.py, hbc_mini.c.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Mirror the same changes from hbc_mini.py: retry host resolution with
exponential backoff (5s→60s) instead of exiting on DNS failure, and add
mutually exclusive -4 / -6 flags to restrict connections to IPv4 or IPv6.
In hbc (main.py) the retry sleep is interruptible via the shutdown_event.
In hbc_mini.c signal handlers are moved before the resolution loop so
SIGINT/SIGTERM can break the retry during startup.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>