Hostinfo day 5: Implement first round of static host commands.
[virt-hostinfo.git] / hostinfod / commands.c
index b928c36..cb66179 100644 (file)
@@ -32,6 +32,7 @@
 #include <ctype.h>
 #include <unistd.h>
 #include <time.h>
+#include <math.h>
 
 #include <apr_general.h>
 #include <apr_pools.h>
@@ -61,6 +62,9 @@ execute_command (const struct timespec *now,
   apr_array_header_t *args;
   struct arg arg;
   command_fn fn;
+  int enabled;
+  double interval;
+  struct timespec *last;
 
   debug ("%s: %s", hval->name, command);
 
@@ -208,8 +212,42 @@ execute_command (const struct timespec *now,
   /* 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);