afb-export: Provide the real path of the binding
[src/app-framework-binder.git] / src / afb-export.c
index 799ad73..e679b76 100644 (file)
@@ -24,6 +24,9 @@
 #include <ctype.h>
 
 #include <json-c/json.h>
+#if !defined(JSON_C_TO_STRING_NOSLASHESCAPE)
+#define JSON_C_TO_STRING_NOSLASHESCAPE 0
+#endif
 
 #define AFB_BINDING_VERSION 0
 #include <afb/afb-binding.h>
@@ -48,6 +51,7 @@
 #include "jobs.h"
 #include "verbose.h"
 #include "sig-monitor.h"
+#include "wrap-json.h"
 
 /*************************************************************************
  * internal types
@@ -136,6 +140,15 @@ struct afb_export
        /* event handler list */
        struct event_handler *event_handlers;
 
+       /* creator if any */
+       struct afb_export *creator;
+
+       /* path indication if any */
+       const char *path;
+
+       /* settings */
+       struct json_object *settings;
+
        /* internal descriptors */
        union {
 #if defined(WITH_LEGACY_BINDING_V1)
@@ -192,6 +205,54 @@ struct afb_api_x3 *afb_export_to_api_x3(struct afb_export *export)
        return to_api_x3(export);
 }
 
+/******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
+       SETTINGS
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************/
+
+static struct json_object *configuration;
+
+void afb_export_set_config(struct json_object *config)
+{
+       struct json_object *save = configuration;
+       configuration = json_object_get(config);
+       json_object_put(save);
+}
+
+static struct json_object *make_settings(struct afb_export *export)
+{
+       struct json_object *result;
+       struct json_object *obj;
+       struct afb_export *iter;
+       char *path;
+
+       /* clone the globals */
+       if (json_object_object_get_ex(configuration, "*", &obj))
+               result = wrap_json_clone(obj);
+       else
+               result = json_object_new_object();
+
+       /* add locals */
+       if (json_object_object_get_ex(configuration, export->name, &obj))
+               wrap_json_object_add(result, obj);
+
+       /* add library path */
+       for (iter = export ; iter && !iter->path ; iter = iter->creator);
+       if (iter) {
+               path = realpath(iter->path, NULL);
+               json_object_object_add(result, "binding-path", json_object_new_string(path));
+               free(path);
+       }
+
+       export->settings = result;
+       return result;
+}
+
 /******************************************************************************
  ******************************************************************************
  ******************************************************************************
@@ -252,7 +313,8 @@ static int event_broadcast_cb(struct afb_api_x3 *closure, const char *name, stru
 
        /* check daemon state */
        if (export->state == Api_State_Pre_Init) {
-               ERROR("[API %s] Bad call to 'afb_daemon_event_broadcast(%s, %s)', must not be in PreInit", export->api.apiname, name, json_object_to_json_string(object));
+               ERROR("[API %s] Bad call to 'afb_daemon_event_broadcast(%s, %s)', must not be in PreInit",
+                       export->api.apiname, name, json_object_to_json_string_ext(object, JSON_C_TO_STRING_NOSLASHESCAPE));
                errno = EINVAL;
                return 0;
        }
@@ -342,7 +404,11 @@ static struct afb_api_x3 *api_new_api_cb(
                void *preinit_closure)
 {
        struct afb_export *export = from_api_x3(closure);
-       struct afb_api_v3 *apiv3 = afb_api_v3_create(export->declare_set, export->call_set, api, info, noconcurrency, preinit, preinit_closure, 1);
+       struct afb_api_v3 *apiv3 = afb_api_v3_create(
+                                       export->declare_set, export->call_set,
+                                       api, info, noconcurrency,
+                                       preinit, preinit_closure, 1,
+                                       export, NULL);
        return apiv3 ? to_api_x3(afb_api_v3_export(apiv3)) : NULL;
 }
 
@@ -863,6 +929,15 @@ static int delete_api_cb(struct afb_api_x3 *api)
        return 0;
 }
 
+static struct json_object *settings_cb(struct afb_api_x3 *api)
+{
+       struct afb_export *export = from_api_x3(api);
+       struct json_object *result = export->settings;
+       if (!result)
+               result = make_settings(export);
+       return result;
+}
+
 static int hooked_api_set_verbs_v2_cb(
                struct afb_api_x3 *api,
                const struct afb_verb_v2 *verbs)
@@ -976,6 +1051,14 @@ static int hooked_delete_api_cb(struct afb_api_x3 *api)
        return result;
 }
 
+static struct json_object *hooked_settings_cb(struct afb_api_x3 *api)
+{
+       struct afb_export *export = from_api_x3(api);
+       struct json_object *result = settings_cb(api);
+       result = afb_hook_api_settings(export, result);
+       return result;
+}
+
 static const struct afb_api_x3_itf api_x3_itf = {
 
        .vverbose = (void*)vverbose_cb,
@@ -1014,6 +1097,7 @@ static const struct afb_api_x3_itf api_x3_itf = {
        .class_require = class_require_cb,
 
        .delete_api = delete_api_cb,
+       .settings = settings_cb,
 };
 
 static const struct afb_api_x3_itf hooked_api_x3_itf = {
@@ -1054,6 +1138,7 @@ static const struct afb_api_x3_itf hooked_api_x3_itf = {
        .class_require = hooked_class_require_cb,
 
        .delete_api = hooked_delete_api_cb,
+       .settings = hooked_settings_cb,
 };
 
 /******************************************************************************
@@ -1149,7 +1234,7 @@ int afb_export_event_handler_add(
        }
 
        /* create the event */
-       handler = malloc(strlen(pattern) + strlen(pattern));
+       handler = malloc(strlen(pattern) + sizeof * handler);
        if (!handler) {
                ERROR("[API %s] can't allocate event handler %s", export->api.apiname, pattern);
                errno = ENOMEM;
@@ -1161,7 +1246,7 @@ int afb_export_event_handler_add(
        handler->callback = callback;
        handler->closure = closure;
        strcpy(handler->pattern, pattern);
-       export->event_handlers = handler;
+       *previous = handler;
 
        return 0;
 }
@@ -1208,9 +1293,11 @@ static struct afb_export *create(
                                struct afb_apiset *declare_set,
                                struct afb_apiset *call_set,
                                const char *apiname,
+                               const char *path,
                                enum afb_api_version version)
 {
        struct afb_export *export;
+       size_t lenapi;
 
        /* session shared with other exports */
        if (common_session == NULL) {
@@ -1218,13 +1305,18 @@ static struct afb_export *create(
                if (common_session == NULL)
                        return NULL;
        }
-       export = calloc(1, sizeof *export + strlen(apiname));
+       lenapi = strlen(apiname);
+       export = calloc(1, sizeof *export + lenapi + (path == apiname || !path ? 0 : strlen(path)));
        if (!export)
                errno = ENOMEM;
        else {
                export->refcount = 1;
                strcpy(export->name, apiname);
                export->api.apiname = export->name;
+               if (path == apiname)
+                       export->path = export->name;
+               else if (path)
+                       export->path = strcpy(&export->name[lenapi + 1], path);
                export->version = version;
                export->state = Api_State_Pre_Init;
                export->session = afb_session_addref(common_session);
@@ -1261,6 +1353,8 @@ void afb_export_destroy(struct afb_export *export)
                afb_session_unref(export->session);
                afb_apiset_unref(export->declare_set);
                afb_apiset_unref(export->call_set);
+               json_object_put(export->settings);
+               afb_export_unref(export->creator);
                if (export->api.apiname != export->name)
                        free((void*)export->api.apiname);
                free(export);
@@ -1274,7 +1368,7 @@ struct afb_export *afb_export_create_none_for_path(
                        int (*creator)(void*, struct afb_api_x3*),
                        void *closure)
 {
-       struct afb_export *export = create(declare_set, call_set, path, Api_Version_None);
+       struct afb_export *export = create(declare_set, call_set, path, path, Api_Version_None);
        if (export) {
                afb_export_logmask_set(export, logmask);
                afb_export_update_hooks(export);
@@ -1287,14 +1381,14 @@ struct afb_export *afb_export_create_none_for_path(
 }
 
 #if defined(WITH_LEGACY_BINDING_V1)
-struct afb_export *afb_export_create_v1(
-                       struct afb_apiset *declare_set,
+struct afb_export *afb_export_create_v1(struct afb_apiset *declare_set,
                        struct afb_apiset *call_set,
                        const char *apiname,
                        int (*init)(struct afb_service_x1),
-                       void (*onevent)(const char*, struct json_object*))
+                       void (*onevent)(const char*, struct json_object*),
+                       const char* path)
 {
-       struct afb_export *export = create(declare_set, call_set, apiname, Api_Version_1);
+       struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_1);
        if (export) {
                export->init.v1 = init;
                export->on_any_event_v12 = onevent;
@@ -1307,16 +1401,16 @@ struct afb_export *afb_export_create_v1(
 }
 #endif
 
-struct afb_export *afb_export_create_v2(
-                       struct afb_apiset *declare_set,
+struct afb_export *afb_export_create_v2(struct afb_apiset *declare_set,
                        struct afb_apiset *call_set,
                        const char *apiname,
                        const struct afb_binding_v2 *binding,
                        struct afb_binding_data_v2 *data,
                        int (*init)(),
-                       void (*onevent)(const char*, struct json_object*))
+                       void (*onevent)(const char*, struct json_object*),
+                       const char* path)
 {
-       struct afb_export *export = create(declare_set, call_set, apiname, Api_Version_2);
+       struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_2);
        if (export) {
                export->init.v2 = init;
                export->on_any_event_v12 = onevent;
@@ -1333,12 +1427,15 @@ struct afb_export *afb_export_create_v2(
 struct afb_export *afb_export_create_v3(struct afb_apiset *declare_set,
                        struct afb_apiset *call_set,
                        const char *apiname,
-                       struct afb_api_v3 *apiv3)
+                       struct afb_api_v3 *apiv3,
+                       struct afb_export* creator,
+                       const char* path)
 {
-       struct afb_export *export = create(declare_set, call_set, apiname, Api_Version_3);
+       struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_3);
        if (export) {
                export->unsealed = 1;
                export->desc.v3 = apiv3;
+               export->creator = afb_export_addref(creator);
                afb_export_logmask_set(export, logmask);
                afb_export_update_hooks(export);
        }
@@ -1729,7 +1826,7 @@ int afb_export_declare(struct afb_export *export,
                        ERROR("can't declare export %s to set %s, ABORTING it!",
                                export->api.apiname,
                                afb_apiset_name(export->declare_set));
-                       afb_export_addref(export);
+                       afb_export_unref(export);
                }
        }
 
@@ -1762,5 +1859,6 @@ void afb_export_process_xreq(struct afb_export *export, struct afb_xreq *xreq)
 void afb_export_context_init(struct afb_export *export, struct afb_context *context)
 {
        afb_context_init(context, export->session, NULL);
+       context->validated = 1;
 }