DAPNETGateway had no MQTT link status at all, and no retain support
in its MQTT layer. Adds a link Kind (linking/unlinked/failed) and
publishes it from the places connectivity already changes state but
was previously only logged: successful login, a rejected auth key
(detected asynchronously from the server's own protocol response, not
the initial TCP connect), a dropped connection triggering the
existing reconnect loop, a failed startup socket open, and clean
shutdown.
The background network thread started by mosquitto_loop_start() was not
being stopped before mosquitto_destroy(), which can cause a use-after-free
if the thread is still running when the mosquitto structure is freed.
The MQTT client ID was generated using sprintf with %ld and time(nullptr).
On platforms with 32-bit userland but 64-bit kernel (such as Raspberry Pi OS
and some custom Alpine Linux builds), time_t is a 64-bit long long but %ld
only reads 32 bits. Since the upper 32 bits of the current Unix timestamp
are zero, this always produces a client ID ending in .0, causing collisions
when multiple instances or restarts occur.
Replace time()-based client IDs with PID-based IDs using getpid(), which is
always a portable 32-bit value and unique per process. Platform-guarded for
Windows (_getpid) and POSIX (getpid).