summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosé Bollo <jose.bollo@iot.bzh>2017-04-11 11:47:27 +0200
committerJosé Bollo <jose.bollo@iot.bzh>2017-04-11 11:47:27 +0200
commit52d837d3964307375018c728120ed649ef0fbb8c (patch)
tree89b09bb428b3f8b9375f60ce28d13ae6aaf6330c
parentca9807f73646f536ac58c002d963a8bb8d245f5d (diff)
Add startup call in command line
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>
-rw-r--r--src/afb-config.c9
-rw-r--r--src/afb-config.h1
-rw-r--r--src/main.c101
3 files changed, 110 insertions, 1 deletions
diff --git a/src/afb-config.c b/src/afb-config.c
index 1b4a3693..0fcb1cb2 100644
--- a/src/afb-config.c
+++ b/src/afb-config.c
@@ -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)
diff --git a/src/afb-config.h b/src/afb-config.h
index 4c9f6241..a636a788 100644
--- a/src/afb-config.h
+++ b/src/afb-config.h
@@ -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;
diff --git a/src/main.c b/src/main.c
index 18f5e5ef..32b12dd3 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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"
@@ -431,6 +434,101 @@ static int execute_command()
}
/*---------------------------------------------------------
+ | 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);