Add startup call in command line
authorJosé Bollo <jose.bollo@iot.bzh>
Tue, 11 Apr 2017 09:47:27 +0000 (11:47 +0200)
committerJosé Bollo <jose.bollo@iot.bzh>
Tue, 11 Apr 2017 09:47:27 +0000 (11:47 +0200)
The option -c (aka --call) allows to specify calls
to api/verb at startup. The calls are made sequentially.

Change-Id: I7f087dce71480fe288cca355c209a4c8ccf4f4b9
Signed-off-by: José Bollo <jose.bollo@iot.bzh>
src/afb-config.c
src/afb-config.h
src/main.c

index 1b4a369..0fcb1cb 100644 (file)
@@ -85,6 +85,7 @@
 
 #define SET_NO_HTTPD       28
 
+#define ADD_CALL           'c'
 #define SET_TRACEDITF      'D'
 #define SET_EXEC           'e'
 #define DISPLAY_HELP       'h'
@@ -97,7 +98,7 @@
 #define SET_VERBOSE        'v'
 #define SET_WORK_DIR       'w'
 
-#define SHORTOPTS      "D:ehqrT:t:u:Vvw:"
+#define SHORTOPTS      "c:D:ehqrT:t:u:Vvw:"
 
 // Command line structure hold cli --command + help text
 typedef struct {
@@ -151,6 +152,7 @@ static AFB_options cliOptions[] = {
 
        {SET_TRACEREQ,      1, "tracereq",    "Log the requests: no, common, extra, all"},
        {SET_TRACEDITF,     1, "traceditf",   "Log the requests: no, common, extra, all"},
+       {ADD_CALL,          1, "call",        "call at start format of val: API/VERB:json-args"},
 
        {SET_NO_HTTPD,      0, "no-httpd",    "Forbids HTTP service"},
        {SET_EXEC,          0, "exec",        "Execute the remaining arguments"},
@@ -437,6 +439,10 @@ static void parse_arguments(int argc, char **argv, struct afb_config *config)
                        list_add(&config->ldpaths, argvalstr(optc));
                        break;
 
+               case ADD_CALL:
+                       list_add(&config->calls, argvalstr(optc));
+                       break;
+
                case SET_SESSION_DIR:
                        /* config->sessiondir = argvalstr(optc); */
                        WARNING("Obsolete otpion %s ignored", optname(optc));
@@ -620,6 +626,7 @@ void afb_config_dump(struct afb_config *config)
        L(ws_servers)
        L(so_bindings)
        L(ldpaths)
+       L(calls)
 
        V(exec)
 
index 4c9f624..a636a78 100644 (file)
@@ -43,6 +43,7 @@ struct afb_config {
        struct afb_config_list *ws_servers;
        struct afb_config_list *so_bindings;
        struct afb_config_list *ldpaths;
+       struct afb_config_list *calls;
 
        char **exec;
 
index 18f5e5e..32b12dd 100644 (file)
@@ -27,6 +27,8 @@
 #include <sys/stat.h>
 #include <sys/wait.h>
 
+#include <json-c/json.h>
+
 #include <systemd/sd-event.h>
 #include <systemd/sd-daemon.h>
 
@@ -41,6 +43,7 @@
 #include "afb-hsrv.h"
 #include "afb-context.h"
 #include "afb-hreq.h"
+#include "afb-xreq.h"
 #include "jobs.h"
 #include "afb-session.h"
 #include "verbose.h"
@@ -430,6 +433,101 @@ static int execute_command()
        return -1;
 }
 
+/*---------------------------------------------------------
+ | startup calls
+ +--------------------------------------------------------- */
+
+struct startup_req
+{
+       struct afb_xreq xreq;
+       char *api;
+       char *verb;
+       struct afb_config_list *current;
+       struct afb_session *session;
+};
+
+static void startup_call_reply(void *closure, int iserror, struct json_object *obj)
+{
+       struct startup_req *sreq = closure;
+
+       if (!iserror)
+               NOTICE("startup call %s returned %s", sreq->current->value, json_object_get_string(obj));
+       else {
+               ERROR("startup call %s ERROR! %s", sreq->current->value, json_object_get_string(obj));
+               exit(1);
+       }
+}
+
+static void startup_call_current(struct startup_req *sreq);
+
+static void startup_call_unref(void *closure)
+{
+       struct startup_req *sreq = closure;
+
+       free(sreq->api);
+       free(sreq->verb);
+       json_object_put(sreq->xreq.json);
+       sreq->current = sreq->current->next;
+       if (sreq->current)
+               startup_call_current(sreq);
+       else {
+               afb_session_close(sreq->session);
+               afb_session_unref(sreq->session);
+               free(sreq);
+       }
+}
+
+static struct afb_xreq_query_itf startup_xreq_itf =
+{
+       .reply = startup_call_reply,
+       .unref = startup_call_unref
+};
+
+static void startup_call_current(struct startup_req *sreq)
+{
+       char *api, *verb, *json;
+
+       api = sreq->current->value;
+       verb = strchr(api, '/');
+       if (verb) {
+               json = strchr(verb, ':');
+               if (json) {
+                       memset(&sreq->xreq, 0, sizeof sreq->xreq);
+                       afb_context_init(&sreq->xreq.context, sreq->session, NULL);
+                       sreq->xreq.context.validated = 1;
+                       sreq->api = strndup(api, verb - api);
+                       sreq->xreq.api = sreq->api;
+                       sreq->verb = strndup(verb + 1, json - verb - 1);
+                       sreq->xreq.verb = sreq->verb;
+                       sreq->xreq.json = json_tokener_parse(json + 1);
+                       sreq->xreq.refcount = 1;
+                       sreq->xreq.query = sreq;
+                       sreq->xreq.queryitf = &startup_xreq_itf;
+                       if (sreq->api && sreq->verb && sreq->xreq.json) {
+                               afb_apis_call(&sreq->xreq);
+                               afb_xreq_unref(&sreq->xreq);
+                               return;
+                       }
+               }
+       }
+       ERROR("Bad call specification %s", sreq->current->value);
+       exit(1);
+}
+
+static void run_startup_calls()
+{
+       struct afb_config_list *list;
+       struct startup_req *sreq;
+
+       list = config->calls;
+       if (list) {
+               sreq = calloc(1, sizeof *sreq);
+               sreq->session = afb_session_create("startup", 3600);
+               sreq->current = list;
+               startup_call_current(sreq);
+       }
+}
+
 /*---------------------------------------------------------
  | job for starting the daemon
  +--------------------------------------------------------- */
@@ -497,6 +595,9 @@ static void start()
 
        /* ready */
        sd_notify(1, "READY=1");
+
+       /* run the startup calls */
+       run_startup_calls();
        return;
 error:
        exit(1);