44#ifndef DEFAULT_QUOTA_DB
45#error "Please define DEFAULT_QUOTA_DB preprocessor constant."
52TDB_CONTEXT *
db =
nullptr;
77 db = tdb_open(
db_path, 0, TDB_CLEAR_IF_FIRST, O_CREAT | O_RDWR, 0666);
93 return ToSBuf(user_key,
"-", sub_key);
96static void writeTime(
const char *user_key,
const char *sub_key, time_t t)
100 reinterpret_cast<unsigned char *
>(
const_cast<char *
>(ks.rawContent())),
103 const TDB_DATA data {
104 reinterpret_cast<unsigned char *
>(&t),
108 tdb_store(
db, key, data, TDB_REPLACE);
112static time_t
readTime(
const char *user_key,
const char *sub_key)
116 reinterpret_cast<unsigned char *
>(
const_cast<char *
>(ks.rawContent())),
119 auto data = tdb_fetch(
db, key);
127 if (data.dsize ==
sizeof(t)) {
128 memcpy(&t, data.dptr,
sizeof(t));
132 "', expected time value size: " <<
sizeof(t) <<
133 ", actual time value size: " << data.dsize);
140static void parseTime(
const char *s, time_t *secs, time_t *start)
145 int periodLength = 3600;
149 ltime = localtime(start);
151 sscanf(s,
" %lf %c", &value, &unit);
158 *start -= ltime->tm_sec;
162 *start -= ltime->tm_min * 60 + ltime->tm_sec;
165 periodLength = 24 * 3600;
166 *start -= ltime->tm_hour * 3600 + ltime->tm_min * 60 + ltime->tm_sec;
169 periodLength = 7 * 24 * 3600;
170 *start -= ltime->tm_hour * 3600 + ltime->tm_min * 60 + ltime->tm_sec;
171 *start -= ltime->tm_wday * 24 * 3600;
179 *secs = (long)(periodLength * value);
196 time_t budgetSecs, periodSecs;
201 FH = fopen(filename,
"r");
204 unsigned int lineCount = 0;
205 while (fgets(line,
sizeof(line), FH)) {
207 if (line[0] ==
'#') {
210 if ((cp = strchr (line,
'\n')) !=
NULL) {
215 if ((username = strtok(line,
"\t ")) !=
NULL) {
218 if ((budget = strtok(
nullptr,
"/")) ==
NULL) {
222 if ((period = strtok(
nullptr,
"/")) ==
NULL) {
231 budgetSecs <<
"s / " << periodSecs <<
"s starting " << start);
248 time_t now = time(
NULL);
250 time_t activityLength;
253 time_t userPeriodLength;
254 time_t timeBudgetCurrent;
255 time_t timeBudgetConfigured;
261 if ( periodStart == 0 ) {
267 periodLength = now - periodStart;
269 if ( userPeriodLength == 0 ) {
272 user_key <<
"': no period length found");
275 if ( periodLength >= userPeriodLength ) {
278 while ( periodStart < now ) {
279 periodStart += periodLength;
283 if ( timeBudgetConfigured == 0 ) {
285 "\". Quota for this user disabled.");
295 if ( lastActivity == 0 ) {
299 activityLength = now - lastActivity;
309 " for user \"" << user_key <<
"\".");
311 timeBudgetCurrent -= activityLength;
318 const auto message =
ToSBuf(
HLP_MSG(
"Remaining quota for '"), user_key,
"' is ", timeBudgetCurrent,
" seconds.");
319 if ( timeBudgetCurrent > 0 ) {
331 "Usage: " <<
program_name <<
" [-d level] [-b dbpath] [-p pauselen] [-h] configfile\n" <<
332 " -d level set section " <<
MY_DEBUG_SECTION <<
" debugging to the specified level,\n"
333 " overwriting Squid's debug_options (default: 1)\n"
334 " -b dbpath Path where persistent session database will be kept\n" <<
335 " If option is not used, then " << DEFAULT_QUOTA_DB <<
" will be used.\n" <<
336 " -p pauselen length in seconds to describe a pause between 2 requests.\n" <<
337 " -h show show command line help.\n" <<
338 "configfile is a file containing time quota definitions.\n";
349 while ((opt =
getopt(argc, argv,
"d:p:b:h")) != -1) {
373 setbuf(stdout,
nullptr);
377 if (
optind + 1 != argc ) {
387 const char *user_key = strtok(request,
" \n");
#define HELPER_INPUT_BUFFER
static void parseOptions(char const *)
static void NameThisHelper(const char *name)
#define debugs(SECTION, LEVEL, CONTENT)
static const auto KeyPeriodStart
static const auto KeyTimeBudgetLeft
static void shutdown_db(void)
static const auto MY_DEBUG_SECTION
static void processActivity(const char *user_key)
static const auto KeyTimeBudgetConfigured
static void writeTime(const char *user_key, const char *sub_key, time_t t)
static void init_db(void)
static time_t readTime(const char *user_key, const char *sub_key)
static void parseTime(const char *s, time_t *secs, time_t *start)
static SBuf KeyString(const char *user_key, const char *sub_key)
static const auto KeyLastActivity
static const size_t TQ_BUFFERSIZE
static void readConfig(const char *filename)
static const auto KeyPeriodLengthConfigured
const char * program_name
int getopt(int nargc, char *const *nargv, const char *ostr)
SBuf ToSBuf(Args &&... args)
slowly stream-prints all arguments into a freshly allocated SBuf