Update copyright dates
[src/app-framework-binder.git] / src / afb-api-dbus.c
index 227658f..7b6134f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015-2018 "IoT.bzh"
+ * Copyright (C) 2015-2020 "IoT.bzh"
  * Author José Bollo <jose.bollo@iot.bzh>
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-#if defined(WITH_DBUS_TRANSPARENCY)
+#if WITH_DBUS_TRANSPARENCY
 
 #define _GNU_SOURCE
 
@@ -33,8 +33,6 @@
 
 #include <afb/afb-event-x2.h>
 
-#include "afb-systemd.h"
-
 #include "afb-session.h"
 #include "afb-msg-json.h"
 #include "afb-api.h"
 #include "afb-cred.h"
 #include "afb-evt.h"
 #include "afb-xreq.h"
-#include "verbose.h"
 
+#include "verbose.h"
+#include "systemd.h"
+#include "jobs.h"
 
 static const char DEFAULT_PATH_PREFIX[] = "/org/agl/afb/api/";
 
@@ -130,7 +130,8 @@ static struct api_dbus *make_api_dbus_3(int system, const char *path, size_t pat
        }
 
        /* choose the bus */
-       sdbus = (system ? afb_systemd_get_system_bus : afb_systemd_get_user_bus)();
+       jobs_acquire_event_manager();
+       sdbus = (system ? systemd_get_system_bus : systemd_get_user_bus)();
        if (sdbus == NULL)
                goto error2;
 
@@ -286,6 +287,8 @@ static int api_dbus_client_on_reply(sd_bus_message *message, void *userdata, sd_
        int rc;
        struct dbus_memo *memo;
        const char *json, *error, *info;
+       struct json_object *object;
+       enum json_tokener_error jerr;
 
        /* retrieve the recorded data */
        memo = userdata;
@@ -297,7 +300,14 @@ static int api_dbus_client_on_reply(sd_bus_message *message, void *userdata, sd_
                afb_xreq_reply(memo->xreq, NULL, "error", "dbus error");
        } else {
                /* report the answer */
-               afb_xreq_reply(memo->xreq, *json ? json_tokener_parse(json) : NULL, *error ? error : NULL, *info ? info : NULL);
+               if (!*json)
+                       object = NULL;
+               else {
+                       object = json_tokener_parse_verbose(json, &jerr);
+                       if (jerr != json_tokener_success)
+                               object = json_object_new_string(json);
+               }
+               afb_xreq_reply(memo->xreq, object, *error ? error : NULL, *info ? info : NULL);
        }
        api_dbus_client_memo_destroy(memo);
        return 1;
@@ -358,12 +368,19 @@ static int api_dbus_client_on_broadcast_event(sd_bus_message *m, void *userdata,
 {
        struct json_object *object;
        const char *event, *data;
-       int rc = sd_bus_message_read(m, "ss", &event, &data);
+       const unsigned char *uuid;
+       size_t szuuid;
+       uint8_t hop;
+       enum json_tokener_error jerr;
+
+       int rc = sd_bus_message_read(m, "ssayy", &event, &data, &uuid, &szuuid, &hop);
        if (rc < 0)
                ERROR("unreadable broadcasted event");
        else {
-               object = json_tokener_parse(data);
-               afb_evt_broadcast(event, object);
+               object = json_tokener_parse_verbose(data, &jerr);
+               if (jerr != json_tokener_success)
+                       object = json_object_new_string(data);
+               afb_evt_rebroadcast(event, object, uuid, hop);
        }
        return 1;
 }
@@ -441,6 +458,7 @@ static void api_dbus_client_event_push(struct api_dbus *api, int id, const char
 {
        struct json_object *object;
        struct dbus_event *ev;
+       enum json_tokener_error jerr;
 
        /* retrieves the event */
        ev = api_dbus_client_event_search(api, id, name);
@@ -450,7 +468,9 @@ static void api_dbus_client_event_push(struct api_dbus *api, int id, const char
        }
 
        /* destroys the event */
-       object = json_tokener_parse(data);
+       object = json_tokener_parse_verbose(data, &jerr);
+       if (jerr != json_tokener_success)
+               object = json_object_new_string(data);
        afb_evt_event_x2_push(ev->event, object);
 }
 
@@ -616,10 +636,10 @@ error:
 
 /******************* event structures for server part **********************************/
 
-static void afb_api_dbus_server_event_add(void *closure, const char *event, int eventid);
-static void afb_api_dbus_server_event_remove(void *closure, const char *event, int eventid);
-static void afb_api_dbus_server_event_push(void *closure, const char *event, int eventid, struct json_object *object);
-static void afb_api_dbus_server_event_broadcast(void *closure, const char *event, int eventid, struct json_object *object);
+static void afb_api_dbus_server_event_add(void *closure, const char *event, uint16_t eventid);
+static void afb_api_dbus_server_event_remove(void *closure, const char *event, uint16_t eventid);
+static void afb_api_dbus_server_event_push(void *closure, const char *event, uint16_t eventid, struct json_object *object);
+static void afb_api_dbus_server_event_broadcast(void *closure, const char *event, struct json_object *object, const uuid_binary_t uuid, uint8_t hop);
 
 /* the interface for events broadcasting */
 static const struct afb_evt_itf evt_broadcast_itf = {
@@ -650,7 +670,7 @@ struct origin
        struct afb_cred *cred;
 
        /* the origin */
-       char name[1];
+       char name[];
 };
 
 /* get the credentials for the message */
@@ -662,6 +682,7 @@ static void init_origin_creds(struct origin *origin)
        gid_t gid;
        pid_t pid;
        const char *context;
+       struct afb_cred *ocred;
 
        rc = sd_bus_get_name_creds(origin->api->sdbus, origin->name,
                        SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_SELINUX_CONTEXT,
@@ -669,13 +690,14 @@ static void init_origin_creds(struct origin *origin)
        if (rc < 0)
                origin->cred = NULL;
        else {
-               afb_cred_unref(origin->cred);
                sd_bus_creds_get_uid(c, &uid);
                sd_bus_creds_get_gid(c, &gid);
                sd_bus_creds_get_pid(c, &pid);
                sd_bus_creds_get_selinux_context(c, &context);
+               ocred = origin->cred;
                origin->cred = afb_cred_create(uid, gid, pid, context);
                sd_bus_creds_unref(c);
+               afb_cred_unref(ocred);
        }
 }
 
@@ -694,7 +716,7 @@ static struct origin *afb_api_dbus_server_origin_get(struct api_dbus *api, const
        }
 
        /* not found, create it */
-       origin = malloc(strlen(sender) + sizeof *origin);
+       origin = malloc(strlen(sender) + 1 + sizeof *origin);
        if (origin == NULL)
                errno = ENOMEM;
        else {
@@ -829,7 +851,7 @@ static int dbus_req_subscribe(struct afb_xreq *xreq, struct afb_event_x2 *event)
        uint64_t msgid;
        int rc;
 
-       rc = afb_evt_event_x2_add_watch(dreq->listener->listener, event);
+       rc = afb_evt_listener_watch_x2(dreq->listener->listener, event);
        sd_bus_message_get_cookie(dreq->message, &msgid);
        afb_api_dbus_server_event_send(dreq->listener->origin, 'S', afb_evt_event_x2_fullname(event), afb_evt_event_x2_id(event), "", msgid);
        return rc;
@@ -843,7 +865,7 @@ static int dbus_req_unsubscribe(struct afb_xreq *xreq, struct afb_event_x2 *even
 
        sd_bus_message_get_cookie(dreq->message, &msgid);
        afb_api_dbus_server_event_send(dreq->listener->origin, 'U', afb_evt_event_x2_fullname(event), afb_evt_event_x2_id(event), "", msgid);
-       rc = afb_evt_event_x2_remove_watch(dreq->listener->listener, event);
+       rc = afb_evt_listener_unwatch_x2(dreq->listener->listener, event);
        return rc;
 }
 
@@ -884,31 +906,32 @@ end:
        sd_bus_message_unref(msg);
 }
 
-static void afb_api_dbus_server_event_add(void *closure, const char *event, int eventid)
+static void afb_api_dbus_server_event_add(void *closure, const char *event, uint16_t eventid)
 {
        afb_api_dbus_server_event_send(closure, '+', event, eventid, "", 0);
 }
 
-static void afb_api_dbus_server_event_remove(void *closure, const char *event, int eventid)
+static void afb_api_dbus_server_event_remove(void *closure, const char *event, uint16_t eventid)
 {
        afb_api_dbus_server_event_send(closure, '-', event, eventid, "", 0);
 }
 
-static void afb_api_dbus_server_event_push(void *closure, const char *event, int eventid, struct json_object *object)
+static void afb_api_dbus_server_event_push(void *closure, const char *event, uint16_t eventid, struct json_object *object)
 {
        const char *data = json_object_to_json_string_ext(object, JSON_C_TO_STRING_PLAIN|JSON_C_TO_STRING_NOSLASHESCAPE);
        afb_api_dbus_server_event_send(closure, '!', event, eventid, data, 0);
        json_object_put(object);
 }
 
-static void afb_api_dbus_server_event_broadcast(void *closure, const char *event, int eventid, struct json_object *object)
+static void afb_api_dbus_server_event_broadcast(void *closure, const char *event, struct json_object *object, const uuid_binary_t uuid, uint8_t hop)
 {
        int rc;
        struct api_dbus *api;
 
        api = closure;
        rc = sd_bus_emit_signal(api->sdbus, api->path, api->name, "broadcast",
-                       "ss", event, json_object_to_json_string_ext(object, JSON_C_TO_STRING_PLAIN|JSON_C_TO_STRING_NOSLASHESCAPE));
+                       "ssayy", event, json_object_to_json_string_ext(object, JSON_C_TO_STRING_PLAIN|JSON_C_TO_STRING_NOSLASHESCAPE),
+                       uuid, UUID_BINARY_LENGTH, hop);
        if (rc < 0)
                ERROR("error while broadcasting event %s", event);
        json_object_put(object);
@@ -926,6 +949,7 @@ static int api_dbus_server_on_object_called(sd_bus_message *message, void *userd
        uint32_t flags;
        struct afb_session *session;
        struct listener *listener;
+       enum json_tokener_error jerr;
 
        /* check the interface */
        if (strcmp(sd_bus_message_get_interface(message), api->name) != 0)
@@ -948,7 +972,7 @@ static int api_dbus_server_on_object_called(sd_bus_message *message, void *userd
 
        /* connect to the context */
        afb_xreq_init(&dreq->xreq, &afb_api_dbus_xreq_itf);
-       if (afb_context_connect(&dreq->xreq.context, uuid, NULL) < 0)
+       if (afb_context_connect(&dreq->xreq.context, uuid, NULL, NULL) < 0)
                goto out_of_memory;
        session = dreq->xreq.context.session;
 
@@ -958,11 +982,11 @@ static int api_dbus_server_on_object_called(sd_bus_message *message, void *userd
                goto out_of_memory;
 
        /* fulfill the request and emit it */
-       dreq->xreq.context.flags = flags;
-       dreq->xreq.cred = afb_cred_mixed_on_behalf_import(listener->origin->cred, uuid, creds && creds[0] ? creds : NULL);
+       afb_context_change_cred(&dreq->xreq.context, listener->origin->cred);
+       afb_context_on_behalf_import(&dreq->xreq.context, creds);
        dreq->message = sd_bus_message_ref(message);
-       dreq->json = json_tokener_parse(dreq->request);
-       if (dreq->json == NULL && strcmp(dreq->request, "null")) {
+       dreq->json = json_tokener_parse_verbose(dreq->request, &jerr);
+       if (jerr != json_tokener_success) {
                /* lazy error detection of json request. Is it to improve? */
                dreq->json = json_object_new_string(dreq->request);
        }