+ _HOOK_XREQ_(unsubscribe, xreq, event, result);
+ return result;
+}
+
+void afb_hook_xreq_subcall(const struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args)
+{
+ _HOOK_XREQ_(subcall, xreq, api, verb, args);
+}
+
+void afb_hook_xreq_subcall_result(const struct afb_xreq *xreq, int status, struct json_object *result)
+{
+ _HOOK_XREQ_(subcall_result, xreq, status, result);
+}
+
+void afb_hook_xreq_subcallsync(const struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args)
+{
+ _HOOK_XREQ_(subcallsync, xreq, api, verb, args);
+}
+
+int afb_hook_xreq_subcallsync_result(const struct afb_xreq *xreq, int status, struct json_object *result)
+{
+ _HOOK_XREQ_(subcallsync_result, xreq, status, result);
+ return status;
+}
+
+/******************************************************************************
+ * section:
+ *****************************************************************************/
+
+void afb_hook_init_xreq(struct afb_xreq *xreq)
+{
+ static int reqindex;
+
+ int f, flags;
+ int add;
+ struct afb_hook_xreq *hook;
+
+ /* scan hook list to get the expected flags */
+ flags = 0;
+ pthread_rwlock_rdlock(&rwlock);
+ hook = list_of_xreq_hooks;
+ while (hook) {
+ f = hook->flags & afb_hook_flags_req_all;
+ add = f != 0
+ && (!hook->session || hook->session == xreq->context.session)
+ && (!hook->api || !strcasecmp(hook->api, xreq->api))
+ && (!hook->verb || !strcasecmp(hook->verb, xreq->verb));
+ if (add)
+ flags |= f;
+ hook = hook->next;
+ }
+ pthread_rwlock_unlock(&rwlock);
+
+ /* store the hooking data */
+ xreq->hookflags = flags;
+ if (flags) {
+ pthread_rwlock_wrlock(&rwlock);
+ if (++reqindex < 0)
+ reqindex = 1;
+ xreq->hookindex = reqindex;
+ pthread_rwlock_unlock(&rwlock);
+ }
+}
+
+struct afb_hook_xreq *afb_hook_create_xreq(const char *api, const char *verb, struct afb_session *session, int flags, struct afb_hook_xreq_itf *itf, void *closure)
+{
+ struct afb_hook_xreq *hook;
+
+ /* alloc the result */
+ hook = calloc(1, sizeof *hook);
+ if (hook == NULL)
+ return NULL;
+
+ /* get a copy of the names */
+ hook->api = api ? strdup(api) : NULL;
+ hook->verb = verb ? strdup(verb) : NULL;
+ if ((api && !hook->api) || (verb && !hook->verb)) {
+ free(hook->api);
+ free(hook->verb);
+ free(hook);
+ return NULL;
+ }
+
+ /* initialise the rest */
+ hook->session = session;
+ if (session)
+ afb_session_addref(session);
+ hook->refcount = 1;
+ hook->flags = flags;
+ hook->itf = itf ? itf : &hook_xreq_default_itf;
+ hook->closure = closure;
+
+ /* record the hook */
+ pthread_rwlock_wrlock(&rwlock);
+ hook->next = list_of_xreq_hooks;
+ list_of_xreq_hooks = hook;
+ pthread_rwlock_unlock(&rwlock);