43#ifndef DEFAULT_QUOTA_DB
44#error "Please define DEFAULT_QUOTA_DB preprocessor constant."
51TDB_CONTEXT *
db =
nullptr;
76 db = tdb_open(
db_path, 0, TDB_CLEAR_IF_FIRST, O_CREAT | O_RDWR, 0666);
92 return ToSBuf(user_key,
"-", sub_key);
95static void writeTime(
const char *user_key,
const char *sub_key, time_t t)
99 reinterpret_cast<unsigned char *
>(
const_cast<char *
>(ks.rawContent())),
102 const TDB_DATA data {
103 reinterpret_cast<unsigned char *
>(&t),
107 tdb_store(
db, key, data, TDB_REPLACE);
111static time_t
readTime(
const char *user_key,
const char *sub_key)
115 reinterpret_cast<unsigned char *
>(
const_cast<char *
>(ks.rawContent())),
118 auto data = tdb_fetch(
db, key);
126 if (data.dsize ==
sizeof(t)) {
127 memcpy(&t, data.dptr,
sizeof(t));
131 "', expected time value size: " <<
sizeof(t) <<
132 ", actual time value size: " << data.dsize);
139static void parseTime(
const char *s, time_t *secs, time_t *start)
144 int periodLength = 3600;
148 ltime = localtime(start);
150 sscanf(s,
" %lf %c", &value, &unit);
157 *start -= ltime->tm_sec;
161 *start -= ltime->tm_min * 60 + ltime->tm_sec;
164 periodLength = 24 * 3600;
165 *start -= ltime->tm_hour * 3600 + ltime->tm_min * 60 + ltime->tm_sec;
168 periodLength = 7 * 24 * 3600;
169 *start -= ltime->tm_hour * 3600 + ltime->tm_min * 60 + ltime->tm_sec;
170 *start -= ltime->tm_wday * 24 * 3600;
178 *secs = (long)(periodLength * value);
195 time_t budgetSecs, periodSecs;
200 FH = fopen(filename,
"r");
203 unsigned int lineCount = 0;
204 while (fgets(line,
sizeof(line), FH)) {
206 if (line[0] ==
'#') {
209 if ((cp = strchr (line,
'\n')) !=
NULL) {
214 if ((username = strtok(line,
"\t ")) !=
NULL) {
217 if ((budget = strtok(
nullptr,
"/")) ==
NULL) {
221 if ((period = strtok(
nullptr,
"/")) ==
NULL) {
230 budgetSecs <<
"s / " << periodSecs <<
"s starting " << start);
247 time_t now = time(
NULL);
249 time_t activityLength;
252 time_t userPeriodLength;
253 time_t timeBudgetCurrent;
254 time_t timeBudgetConfigured;
260 if ( periodStart == 0 ) {
266 periodLength = now - periodStart;
268 if ( userPeriodLength == 0 ) {
271 user_key <<
"': no period length found");
274 if ( periodLength >= userPeriodLength ) {
277 while ( periodStart < now ) {
278 periodStart += periodLength;
282 if ( timeBudgetConfigured == 0 ) {
284 "\". Quota for this user disabled.");
294 if ( lastActivity == 0 ) {
298 activityLength = now - lastActivity;
308 " for user \"" << user_key <<
"\".");
310 timeBudgetCurrent -= activityLength;
317 const auto message =
ToSBuf(
HLP_MSG(
"Remaining quota for '"), user_key,
"' is ", timeBudgetCurrent,
" seconds.");
318 if ( timeBudgetCurrent > 0 ) {
330 "Usage: " <<
program_name <<
" [-d level] [-b dbpath] [-p pauselen] [-h] configfile\n" <<
331 " -d level set section " <<
MY_DEBUG_SECTION <<
" debugging to the specified level,\n"
332 " overwriting Squid's debug_options (default: 1)\n"
333 " -b dbpath Path where persistent session database will be kept\n" <<
334 " If option is not used, then " << DEFAULT_QUOTA_DB <<
" will be used.\n" <<
335 " -p pauselen length in seconds to describe a pause between 2 requests.\n" <<
336 " -h show show command line help.\n" <<
337 "configfile is a file containing time quota definitions.\n";
348 while ((opt =
getopt(argc, argv,
"d:p:b:h")) != -1) {
372 setbuf(stdout,
nullptr);
376 if (
optind + 1 != argc ) {
386 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