A subscribe is a short request: the server answers immediately and the
device then relies on push notifications. Unlike a listen, nothing keeps
it under observation. The keepalive is only armed once the server has
answered, and no request in this client ever sets a timeout, so a
subscribe stalled in name resolution, connection or TLS handshake never
completes and never fails either.
The listener then stays registered locally while the server never learns
about it: the device stops being notified, without anything reporting an
error. This is most likely right after a wake-up, when the network stack
is still settling.
Arm a deadline on subscribe requests and fail the operation when it
expires, so restartListeners() sends the subscription again. Streaming
listens are left untouched: they are long lived by design.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This prevents ThreadPool::stop from hanging if it is called with `wait`
set to true (which is notably the case in ThreadPool::join) and the
pool's task queue is non-empty.
Make Hash default constructor, hex constructor, data(), const
operator[] and fromString constexpr. Change fromString to be
non-throwing: it now uses a validity flag and fills the hash with zeros
on parse error instead of throwing. Add a constexpr toHexArray helper
that returns a std::array<char, N*2> for compile-time hex conversion.
Update tests to include <string_view>, use std::string_view, add
constexpr InfoHash usage and a static_assert for the hex array.
Change the template unpackMsg to accept a const Blob& to avoid an
unnecessary copy of the Blob argument. Move the non-template unpackMsg
(returning msgpack::unpacked) into the header as an inline function and
remove its out-of-line definition from src/utils.cpp. Update
declarations accordingly.