+static void in_after (afb_req_t request)
+{
+ int rc;
+ const char *ts, *ty;
+ char *te;
+ double td;
+ struct timespec t;
+
+ /* get the type */
+ ty = afb_req_value(request, "type") ?: "call";
+ if (strcmp(ty, "call") && strcmp(ty, "callsync")
+ && strcmp(ty, "subcall") && strcmp(ty, "subcallsync"))
+ return afb_req_reply(request, NULL, "invalid", "bad type");
+
+ /* get the delay */
+ ts = afb_req_value(request, "delay");
+ if (!ts)
+ return afb_req_reply(request, NULL, "invalid", "no delay");
+ td = strtod(ts, &te);
+ if (*te || td < 0 || td > 3e6) /* a month is the biggest accepted */
+ return afb_req_reply(request, NULL, "invalid", "bad delay");
+
+ /* wait for that time */
+ if (td > 0) {
+ t.tv_nsec = (long)(1e6 * modf(td, &td));
+ t.tv_sec = (time_t)td;
+ do {
+ rc = nanosleep(&t, &t);
+ } while (rc != 0 && errno == EINTR);
+
+ if (rc)
+ return afb_req_reply(request, NULL, "error", "sleep failed");
+ }
+
+ /* do the call */
+ if (!strcmp(ty, "subcallsync"))
+ subcall(request);
+ else if (!strcmp(ty, "subcall"))
+ subcallsync(request);
+ else if (!strcmp(ty, "callsync"))
+ callsync(request);
+ else
+ call(request);
+}
+
+static void *thread_after (void *closure)
+{
+ afb_req_t request = closure;
+ in_after (request);
+ afb_req_unref(request);
+ return NULL;
+}
+
+static void after (afb_req_t request)
+{
+ int rc;
+ pthread_t tid;
+ pthread_attr_t attr;
+
+ afb_req_addref(request);
+
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ rc =pthread_create(&tid, &attr, thread_after, request);
+ pthread_attr_destroy(&attr);
+
+ if (rc != 0) {
+ afb_req_unref(request);
+ afb_req_reply(request, NULL, "cant-start", NULL);
+ }
+}
+