#include <ctype.h>
#include <unistd.h>
#include <time.h>
+#include <math.h>
#include <apr_general.h>
#include <apr_pools.h>
apr_array_header_t *args;
struct arg arg;
command_fn fn;
+ int enabled;
+ double interval;
+ struct timespec *last;
debug ("%s: %s", hval->name, command);
*/
len = strlen (command);
if (len < 1 || len > 4094 || not_printable (command)) {
- warning ("%s: command too short, too long or contained unprintable chars (len = %d)",
+ warning ("%s: command too short, too long or contained unprintable chars (len = %zu)",
hval->name, len);
send_error (hval, 400);
return;
default:
unknown_arg:
- warning ("%s: unknown or malformed argument starting at position %d ('%c')",
+ warning ("%s: unknown or malformed argument starting at position %zu ('%c')",
hval->name, i, command[i]);
send_error (hval, 400);
return;
switch (arg.type) {
case arg_type_bool:
case arg_type_int:
- debug ("%s: arg %d : %s = %ld",
+ debug ("%s: arg %zu : %s = %ld",
hval->name, i, string_of_arg_type (arg.type), arg.u.i);
break;
case arg_type_string:
- debug ("%s: arg %d : %s = %s",
+ debug ("%s: arg %zu : %s = %s",
hval->name, i, string_of_arg_type (arg.type), arg.u.str);
break;
}
/* Before dispatching the command, check the command is enabled
* and guest is not calling it too frequently.
*/
- error ("XXXXXXX enabled check not implemented XXXXXXX");
- error ("XXXXXXX frequency check not implemented XXXXXXX");
+ check_guests_file (hval, cmd, &interval, &enabled);
+
+ if (!enabled) {
+ warning ("%s: guest tried disabled command '%s'", hval->name, cmd);
+ send_error (hval, 401);
+ return;
+ }
+
+ last = apr_hash_get (hval->lasttime, cmd, APR_HASH_KEY_STRING);
+ if (last) {
+ struct timespec timediff;
+ double interval_int, interval_frac;
+ struct timespec interval_ts;
+
+ diff_timespec (&timediff, now, last);
+
+ interval_frac = modf (interval, &interval_int);
+ interval_ts.tv_sec = interval_int;
+ interval_ts.tv_nsec = interval_frac * 1000000000;
+
+ debug ("%s: %s: interval %ds %ldns, time since last %ds %ldns",
+ hval->name, cmd,
+ (int) interval_ts.tv_sec, interval_ts.tv_nsec,
+ (int) timediff.tv_sec, timediff.tv_nsec);
+
+ if (interval_ts.tv_sec > timediff.tv_sec ||
+ (interval_ts.tv_sec == timediff.tv_sec &&
+ interval_ts.tv_nsec > timediff.tv_nsec)) {
+ warning ("%s: command '%s' exceeded interval allowed", hval->name, cmd);
+ send_error (hval, 406);
+ return;
+ }
+ }
+
+ last = apr_pmemdup (hval->pool, now, sizeof *now);
+ apr_hash_set (hval->lasttime, cmd, APR_HASH_KEY_STRING, last);
/* Dispatch the command. */
fn (hval, cmd, args);