+ std::unordered_map<int, Client> clients;
+
+ // A list of all clients, ordered by the time they connected (first element),
+ // and their file descriptor (second element). It is ordered by connection time
+ // (and thus also by read timeout time) so that we can read clients from the
+ // start and stop processing once we get to one that isn't ready to be
+ // timed out yet (which means we only have to look at each client exactly once,
+ // save for the first element of the queue, which is always checked).
+ //
+ // Note that when we delete a client, we don't update this queue.
+ // This means that when reading it, we need to check if the client it
+ // describes is still exists (ie., that the fd still exists, and that
+ // the timespec matches).
+ std::queue<std::pair<timespec, int>> clients_ordered_by_connect_time;
+
+ // HLS is harder to keep viewer statistics for than regular streams,
+ // since there's no 1:1 mapping between ongoing HTTP connections and
+ // actual viewers. After a HLS fragment has been successfully sent,
+ // we keep a note of that in this structure, so that we can add some
+ // fake entries in the .stats file for clients that we believe are still
+ // watching, but are not downloading anything right now. We clean this
+ // out whenever we write statistics centrally.
+ //
+ // The structure is keyed by X-Playback-Session-Id if it exists
+ // (typically iOS clients) or IP address otherwise; we can't use the socket,
+ // since clients can (and do) keep open multiple HTTP connections for
+ // the same video playack session, and may also close the socket
+ // between downloading fragments. This means multiple clients between
+ // the same NAT may be undercounted, but that's how it is.
+ std::unordered_map<std::string, HLSZombie> hls_zombies;