Update date of copyright notices
[src/app-framework-binder.git] / src / afs-supervisor.c
index 8d76832..acad792 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016, 2017 "IoT.bzh"
+ * Copyright (C) 2016, 2017, 2018 "IoT.bzh"
  * Author José Bollo <jose.bollo@iot.bzh>
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
 #include <errno.h>
 #include <signal.h>
 #include <unistd.h>
-#include <fcntl.h>
 #include <pthread.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/un.h>
 
-#include <systemd/sd-event.h>
-#include <systemd/sd-daemon.h>
-
-#include <uuid/uuid.h>
 #include <json-c/json.h>
 #include <afb/afb-binding-v2.h>
 
-#include "afs-supervision.h"
-#include "afb-common.h"
-#include "afb-session.h"
 #include "afb-cred.h"
 #include "afb-stub-ws.h"
 #include "afb-api.h"
 #include "afb-xreq.h"
 #include "afb-api-so-v2.h"
-#include "afb-api-ws.h"
 #include "afb-apiset.h"
-#include "jobs.h"
+#include "afb-fdev.h"
+
+#include "fdev.h"
 #include "verbose.h"
 #include "wrap-json.h"
 
+#include "afs-supervision.h"
+#include "afs-supervisor.h"
+#include "afs-discover.h"
+
 /* supervised items */
 struct supervised
 {
@@ -63,17 +60,15 @@ struct supervised
 };
 
 /* api and apiset name */
-static const char supervision_apiname[] = AFS_SURPERVISION_APINAME_INTERNAL;
-static const char supervisor_apiname[] = "supervisor";
-
-/* the main apiset */
-struct afb_apiset *main_apiset;
+static const char supervision_apiname[] = AFS_SURPERVISION_APINAME;
+static const char supervisor_apiname[] = AFS_SURPERVISOR_APINAME;
 
 /* the empty apiset */
 static struct afb_apiset *empty_apiset;
 
 /* supervision socket path */
 static const char supervision_socket_path[] = AFS_SURPERVISION_SOCKET;
+static struct fdev *supervision_fdev;
 
 /* global mutex */
 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -83,7 +78,6 @@ static struct supervised *superviseds;
 
 /*************************************************************************************/
 
-static int afb_init_supervision_api();
 
 /*************************************************************************************/
 
@@ -191,13 +185,20 @@ static void on_supervised_hangup(struct afb_stub_ws *stub)
 static int make_supervised(int fd, struct afb_cred *cred)
 {
        struct supervised *s;
+       struct fdev *fdev;
 
        s = malloc(sizeof *s);
        if (!s)
                return -1;
 
+       fdev = afb_fdev_create(fd);
+       if (!fdev) {
+               free(s);
+               return -1;
+       }
+
        s->cred = cred;
-       s->stub = afb_stub_ws_create_client(fd, supervision_apiname, empty_apiset);
+       s->stub = afb_stub_ws_create_client(fdev, supervision_apiname, empty_apiset);
        if (!s->stub) {
                free(s);
                return -1;
@@ -210,6 +211,22 @@ static int make_supervised(int fd, struct afb_cred *cred)
        return 0;
 }
 
+/**
+ * Search the supervised of 'pid', return it or NULL.
+ */
+static struct supervised *supervised_of_pid(pid_t pid)
+{
+       struct supervised *s;
+
+       pthread_mutex_lock(&mutex);
+       s = superviseds;
+       while (s && pid != s->cred->pid)
+               s = s->next;
+       pthread_mutex_unlock(&mutex);
+
+       return s;
+}
+
 /*
  * handles incoming connection on 'sock'
  */
@@ -241,113 +258,37 @@ static void accept_supervision_link(int sock)
 /*
  * handle even on server socket
  */
-static int listening(sd_event_source *src, int fd, uint32_t revents, void *closure)
+static void listening(void *closure, uint32_t revents, struct fdev *fdev)
 {
        if ((revents & EPOLLIN) != 0)
-               accept_supervision_link(fd);
+               accept_supervision_link((int)(intptr_t)closure);
        if ((revents & EPOLLHUP) != 0) {
                ERROR("supervision socket closed");
                exit(1);
        }
-       return 0;
 }
 
-
-/**
- * initalize the supervision
+/*
  */
-static int init(const char *spec)
+static void discovered_cb(void *closure, pid_t pid)
 {
-       int rc, fd;
-
-       /* check argument */
-       if (!spec) {
-               ERROR("invalid socket spec");
-               return -1;
-       }
-
-       rc = afb_session_init(100, 600, "");
-       /* TODO check that value */
-
-       /* create the apisets */
-       main_apiset = afb_apiset_create(supervisor_apiname, 0);
-       if (!main_apiset) {
-               ERROR("Can't create supervisor's apiset");
-               return -1;
-       }
-       empty_apiset = afb_apiset_create(supervision_apiname, 0);
-       if (!empty_apiset) {
-               ERROR("Can't create supervision apiset");
-               return -1;
-       }
-
-
-       /* init the main apiset */
-       rc = afb_init_supervision_api();
-       if (rc < 0) {
-               ERROR("Can't create supervision's apiset: %m");
-               return -1;
-       }
-
-       /* create the supervision socket */
-       fd = create_supervision_socket(supervision_socket_path);
-       if (fd < 0)
-               return fd;
-
-       /* listen the socket */
-       rc = listen(fd, 5);
-       if (rc < 0) {
-               ERROR("refused to listen on socket");
-               return rc;
-       }
-
-       /* integrate the socket to the loop */
-       rc = sd_event_add_io(afb_common_get_event_loop(),
-                               NULL, fd, EPOLLIN,
-                               listening, NULL);
-       if (rc < 0) {
-               ERROR("handling socket event isn't possible");
-               return rc;
-       }
+       struct supervised *s;
 
-       /* adds the server socket */
-       rc = afb_api_ws_add_server(spec, main_apiset);
-       if (rc < 0) {
-               ERROR("can't start the server socket");
-               return -1;
+       s = supervised_of_pid(pid);
+       if (!s) {
+               (*(int*)closure)++;
+               kill(pid, SIGHUP);
        }
-       return 0;
-}
-
-/* start should not be null but */
-static void start(int signum, void *arg)
-{
-       char *xpath = arg;
-       int rc;
-
-       if (signum)
-               exit(1);
-
-       rc = init(xpath);
-       if (rc)
-               exit(1);
-
-       sd_notify(1, "READY=1");
 }
 
-/**
- * initalize the supervision
- */
-int main(int ac, char **av)
+int afs_supervisor_discover()
 {
-       verbosity = Verbosity_Level_Debug;
-       /* enter job processing */
-       jobs_start(3, 0, 10, start, av[1]);
-       WARNING("hoops returned from jobs_enter! [report bug]");
-       return 1;
+       int n = 0;
+       afs_discover("afb-daemon", discovered_cb, &n);
+       return n;
 }
 
-/*********************************************************************************************************/
+/*************************************************************************************/
 
 static struct afb_binding_data_v2 datav2;
 
@@ -376,6 +317,12 @@ static void f_list(struct afb_req req)
        afb_req_success(req, resu, NULL);
 }
 
+static void f_discover(struct afb_req req)
+{
+       afs_supervisor_discover();
+       afb_req_success(req, NULL, NULL);
+}
+
 static void propagate(struct afb_req req, const char *verb)
 {
        struct afb_xreq *xreq;
@@ -396,9 +343,7 @@ static void propagate(struct afb_req req, const char *verb)
                afb_xreq_fail(xreq, "bad-pid", NULL);
                return;
        }
-       s = superviseds;
-       while (s && p != (int)s->cred->pid)
-               s = s->next;
+       s = supervised_of_pid((pid_t)p);
        if (!s) {
                afb_req_fail(req, "unknown-pid", NULL);
                return;
@@ -438,19 +383,64 @@ static void f_session_close(struct afb_req req)
 static void f_exit(struct afb_req req)
 {
        propagate(req, NULL);
+       afb_req_success(req, NULL, NULL);
 }
 
 static void f_debug_wait(struct afb_req req)
 {
        propagate(req, "wait");
+       afb_req_success(req, NULL, NULL);
 }
 
 static void f_debug_break(struct afb_req req)
 {
        propagate(req, "break");
+       afb_req_success(req, NULL, NULL);
 }
 
-static const struct afb_auth _afb_auths_v2_supervision[] = {
+/*************************************************************************************/
+
+/**
+ * initalize the supervisor
+ */
+static int init_supervisor()
+{
+       int rc, fd;
+
+       /* create an empty set for superviseds */
+       empty_apiset = afb_apiset_create(supervision_apiname, 0);
+       if (!empty_apiset) {
+               ERROR("Can't create supervision apiset");
+               return -1;
+       }
+
+       /* create the supervision socket */
+       fd = create_supervision_socket(supervision_socket_path);
+       if (fd < 0)
+               return fd;
+
+       /* listen the socket */
+       rc = listen(fd, 5);
+       if (rc < 0) {
+               ERROR("refused to listen on socket");
+               return rc;
+       }
+
+       /* integrate the socket to the loop */
+       supervision_fdev = afb_fdev_create(fd);
+       if (rc < 0) {
+               ERROR("handling socket event isn't possible");
+               return rc;
+       }
+       fdev_set_events(supervision_fdev, EPOLLIN);
+       fdev_set_callback(supervision_fdev, listening, (void*)(intptr_t)fd);
+
+       return 0;
+}
+
+/*************************************************************************************/
+
+static const struct afb_auth _afb_auths_v2_supervisor[] = {
        /* 0 */
        {
                .type = afb_auth_Permission,
@@ -458,86 +448,93 @@ static const struct afb_auth _afb_auths_v2_supervision[] = {
        }
 };
 
-static const struct afb_verb_v2 _afb_verbs_v2_supervision[] = {
+static const struct afb_verb_v2 _afb_verbs_v2_supervisor[] = {
     {
         .verb = "list",
         .callback = f_list,
-        .auth = &_afb_auths_v2_supervision[0],
+        .auth = &_afb_auths_v2_supervisor[0],
         .info = NULL,
-        .session = AFB_SESSION_NONE_V2
+        .session = AFB_SESSION_CHECK_V2
     },
     {
         .verb = "config",
         .callback = f_config,
-        .auth = &_afb_auths_v2_supervision[0],
+        .auth = &_afb_auths_v2_supervisor[0],
         .info = NULL,
-        .session = AFB_SESSION_NONE_V2
+        .session = AFB_SESSION_CHECK_V2
     },
     {
         .verb = "do",
         .callback = f_do,
-        .auth = &_afb_auths_v2_supervision[0],
+        .auth = &_afb_auths_v2_supervisor[0],
         .info = NULL,
-        .session = AFB_SESSION_NONE_V2
+        .session = AFB_SESSION_CHECK_V2
     },
     {
         .verb = "trace",
         .callback = f_trace,
-        .auth = &_afb_auths_v2_supervision[0],
+        .auth = &_afb_auths_v2_supervisor[0],
         .info = NULL,
-        .session = AFB_SESSION_NONE_V2
+        .session = AFB_SESSION_CHECK_V2
     },
     {
         .verb = "sessions",
         .callback = f_sessions,
-        .auth = &_afb_auths_v2_supervision[0],
+        .auth = &_afb_auths_v2_supervisor[0],
         .info = NULL,
-        .session = AFB_SESSION_NONE_V2
+        .session = AFB_SESSION_CHECK_V2
     },
     {
         .verb = "session-close",
         .callback = f_session_close,
-        .auth = &_afb_auths_v2_supervision[0],
+        .auth = &_afb_auths_v2_supervisor[0],
         .info = NULL,
-        .session = AFB_SESSION_NONE_V2
+        .session = AFB_SESSION_CHECK_V2
     },
     {
         .verb = "exit",
         .callback = f_exit,
-        .auth = &_afb_auths_v2_supervision[0],
+        .auth = &_afb_auths_v2_supervisor[0],
         .info = NULL,
-        .session = AFB_SESSION_NONE_V2
+        .session = AFB_SESSION_CHECK_V2
     },
     {
         .verb = "debug-wait",
         .callback = f_debug_wait,
-        .auth = &_afb_auths_v2_supervision[0],
+        .auth = &_afb_auths_v2_supervisor[0],
         .info = NULL,
-        .session = AFB_SESSION_NONE_V2
+        .session = AFB_SESSION_CHECK_V2
     },
     {
         .verb = "debug-break",
         .callback = f_debug_break,
-        .auth = &_afb_auths_v2_supervision[0],
+        .auth = &_afb_auths_v2_supervisor[0],
+        .info = NULL,
+        .session = AFB_SESSION_CHECK_V2
+    },
+    {
+        .verb = "discover",
+        .callback = f_discover,
+        .auth = &_afb_auths_v2_supervisor[0],
         .info = NULL,
-        .session = AFB_SESSION_NONE_V2
+        .session = AFB_SESSION_CHECK_V2
     },
     { .verb = NULL }
 };
 
-static const struct afb_binding_v2 _afb_binding_v2_supervision = {
+static const struct afb_binding_v2 _afb_binding_v2_supervisor = {
     .api = supervisor_apiname,
     .specification = NULL,
     .info = NULL,
-    .verbs = _afb_verbs_v2_supervision,
+    .verbs = _afb_verbs_v2_supervisor,
     .preinit = NULL,
-    .init = NULL,
+    .init = init_supervisor,
     .onevent = NULL,
     .noconcurrency = 0
 };
 
-static int afb_init_supervision_api()
+int afs_supervisor_add(struct afb_apiset *apiset)
 {
-       return afb_api_so_v2_add_binding(&_afb_binding_v2_supervision, NULL, main_apiset, &datav2);
+       return afb_api_so_v2_add_binding(&_afb_binding_v2_supervisor, NULL, apiset, &datav2);
 }