VoltMod
C++23 framework for CS2 server plugins
Loading...
Searching...
No Matches
PendingConVarQueries.hpp
Go to the documentation of this file.
1#pragma once
2
5#include <array>
6#include <cstdint>
7#include <optional>
8#include <string>
9#include <string_view>
10#include <vector>
11
12namespace VoltMod
13{
14
15/** @brief One outstanding client convar query, identified by the cookie sent to the client. */
17{
18 std::string Name; ///< Convar name the query asked for.
19 ClientConVars::QueryCallback Callback; ///< Invoked once, when a matching answer arrives.
20 double SentAtSec = 0.0; ///< Caller-supplied monotonic timestamp of the send.
21 int Cookie = -1; ///< Cookie sent to the client; matched on the answer.
22};
23
24/**
25 * @brief Bookkeeping for @ref ClientConVars: per-slot, cookie-keyed queries awaiting an answer.
26 *
27 * Split out of the service so the matching and expiry rules are testable without the SDK. Time is
28 * caller-supplied (seconds, any monotonic origin) and expiry is lazy: nothing is dropped until the
29 * next Prune() for that slot, which the service runs on every Query().
30 *
31 * A client need never answer, so the table is capped per slot - beyond @ref MaxPendingPerSlot,
32 * queries are refused rather than queued behind a silent client.
33 */
35{
36public:
37 /** Outstanding queries allowed per slot before Query() starts refusing. */
38 static constexpr size_t MaxPendingPerSlot = 11;
39
40 /** Age at which an unanswered query is dropped, in seconds. */
41 static constexpr double TimeoutSec = 10.0;
42
43 /** Largest cookie handed out; the protobuf field is an int32. */
44 static constexpr uint32_t MaxCookie = 0x7FFFFFFF;
45
46 /** Drop @p slot's queries older than @ref TimeoutSec. Their callbacks never fire. */
47 void Prune(int slot, double now);
48
49 /** The query for @p name already in flight on @p slot, or null. */
50 PendingConVarQuery* Find(int slot, std::string_view name);
51
52 /** True when @p slot has no room for another query. */
53 bool Full(int slot) const;
54
55 /**
56 * Next cookie unused on @p slot, or -1 when none could be found. Cookies increase
57 * monotonically and wrap back to 1 at @ref MaxCookie.
58 */
59 int NextCookie(int slot);
60
61 /** Track a query sent with a cookie from @ref NextCookie. */
62 void Add(int slot, int cookie, std::string name, ClientConVars::QueryCallback callback, double now);
63
64 /**
65 * Remove and return @p slot's query @p cookie, but only when @p name matches the convar it
66 * asked for: a client answering with a different name is answering a question nobody posed.
67 */
68 std::optional<PendingConVarQuery> Take(int slot, int cookie, std::string_view name);
69
70 void Clear(int slot);
71 void ClearAll();
72
73 size_t Count(int slot) const;
74
75private:
76 // A slot holds at most MaxPendingPerSlot entries, so a flat vector beats a keyed container on
77 // every operation here - all of which already scan.
78 std::array<std::vector<PendingConVarQuery>, MaxPlayers> _slots;
79 uint32_t _cookieCounter = 0;
80};
81
82} // namespace VoltMod
std::function< void(int slot, ClientConVarStatus status, std::string_view name, std::string_view value)> QueryCallback
Bookkeeping for ClientConVars: per-slot, cookie-keyed queries awaiting an answer.
void Add(int slot, int cookie, std::string name, ClientConVars::QueryCallback callback, double now)
static constexpr size_t MaxPendingPerSlot
std::optional< PendingConVarQuery > Take(int slot, int cookie, std::string_view name)
void Prune(int slot, double now)
static constexpr uint32_t MaxCookie
PendingConVarQuery * Find(int slot, std::string_view name)
static std::string ReadFile(const std::filesystem::path &path)
Definition Loader.cpp:56
constexpr int MaxPlayers
Definition Slot.hpp:7
One outstanding client convar query, identified by the cookie sent to the client.
std::string Name
Convar name the query asked for.
double SentAtSec
Caller-supplied monotonic timestamp of the send.
int Cookie
Cookie sent to the client; matched on the answer.
ClientConVars::QueryCallback Callback
Invoked once, when a matching answer arrives.