diff options
author | José Bollo <jose.bollo@iot.bzh> | 2016-05-19 16:27:21 +0200 |
---|---|---|
committer | José Bollo <jose.bollo@iot.bzh> | 2016-05-19 16:27:21 +0200 |
commit | 8b9507105bb29e2b88b7c51c82ced38dca7f9e13 (patch) | |
tree | 57f905fa05a63bb4813360dc7be9dfac6649e735 /plugins | |
parent | ae7f9ff4ba5f58c90cd0b9f4ed17978b66a9c0b2 (diff) |
afm-main-api: plugin moved to afm-main
Change-Id: I627a698e17020e8437fa0045d7a35353f216d1e5
Signed-off-by: José Bollo <jose.bollo@iot.bzh>
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/afm-main-plugin/CMakeLists.txt | 20 | ||||
-rw-r--r-- | plugins/afm-main-plugin/afm-main-plugin.c | 365 | ||||
-rw-r--r-- | plugins/afm-main-plugin/export.map | 1 | ||||
-rw-r--r-- | plugins/afm-main-plugin/utils-jbus.c | 975 | ||||
-rw-r--r-- | plugins/afm-main-plugin/utils-jbus.h | 133 |
5 files changed, 0 insertions, 1494 deletions
diff --git a/plugins/afm-main-plugin/CMakeLists.txt b/plugins/afm-main-plugin/CMakeLists.txt deleted file mode 100644 index 6da0e915..00000000 --- a/plugins/afm-main-plugin/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ - -INCLUDE(FindPkgConfig) -PKG_CHECK_MODULES(libsystemd REQUIRED libsystemd>=222) - -INCLUDE_DIRECTORIES( - ${INCLUDE_DIRS} - ${libsystemd_INCLUDE_DIRS} -) - - -ADD_LIBRARY(afm-main-api MODULE afm-main-plugin.c utils-jbus.c) -SET_TARGET_PROPERTIES(afm-main-api PROPERTIES - PREFIX "" - LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/export.map" -) - -TARGET_LINK_LIBRARIES(afm-main-api ${link_libraries} ${libsystemd_LIBRARIES}) -INCLUDE_DIRECTORIES(${include_dirs}) -INSTALL(TARGETS afm-main-api - LIBRARY DESTINATION ${plugin_install_dir}) diff --git a/plugins/afm-main-plugin/afm-main-plugin.c b/plugins/afm-main-plugin/afm-main-plugin.c deleted file mode 100644 index 786468a1..00000000 --- a/plugins/afm-main-plugin/afm-main-plugin.c +++ /dev/null @@ -1,365 +0,0 @@ -/* - * Copyright (C) 2015, 2016 "IoT.bzh" - * Author "Fulup Ar Foll" - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define _GNU_SOURCE /* See feature_test_macros(7) */ -#include <stdio.h> -#include <string.h> -#include <assert.h> -#include <json-c/json.h> - -#include <afb/afb-plugin.h> - -#include "utils-jbus.h" - -static const char _added_[] = "added"; -static const char _auto_[] = "auto"; -static const char _continue_[] = "continue"; -static const char _changed_[] = "changed"; -static const char _detail_[] = "detail"; -static const char _id_[] = "id"; -static const char _install_[] = "install"; -static const char _local_[] = "local"; -static const char _mode_[] = "mode"; -static const char _remote_[] = "remote"; -static const char _runid_[] = "runid"; -static const char _runnables_[] = "runnables"; -static const char _runners_[] = "runners"; -static const char _start_[] = "start"; -static const char _state_[] = "state"; -static const char _stop_[] = "stop"; -static const char _terminate_[] = "terminate"; -static const char _uninstall_[] = "uninstall"; -static const char _uri_[] = "uri"; - -static const struct AFB_interface *afb_interface; -static struct afb_event_sender event_sender; - -static struct jbus *jbus; - -struct memo -{ - struct afb_req request; - const char *method; -}; - -static struct memo *make_memo(struct afb_req request, const char *method) -{ - struct memo *memo = malloc(sizeof *memo); - if (memo != NULL) { - memo->request = request; - memo->method = method; - afb_req_addref(request); - } - return memo; -} - -static void application_list_changed(const char *data, void *closure) -{ - afb_event_sender_push(event_sender, "application-list-changed", NULL); -} - -static struct json_object *embed(const char *tag, struct json_object *obj) -{ - struct json_object *result; - - if (obj == NULL) - result = NULL; - else if (!tag) - result = obj; - else { - result = json_object_new_object(); - if (result == NULL) { - /* can't embed */ - result = obj; - } - else { - /* TODO why is json-c not returning a status? */ - json_object_object_add(result, tag, obj); - } - } - return result; -} - -static void embed_call_void_callback(int status, struct json_object *obj, struct memo *memo) -{ - if (afb_interface->verbosity) - fprintf(stderr, "(afm-main-plugin) %s(true) -> %s\n", memo->method, - obj ? json_object_to_json_string(obj) : "NULL"); - if (obj == NULL) { - afb_req_fail(memo->request, "failed", "framework daemon failure"); - } else { - obj = json_object_get(obj); - obj = embed(memo->method, obj); - if (obj == NULL) { - afb_req_fail(memo->request, "failed", "framework daemon failure"); - } else { - afb_req_success(memo->request, obj, NULL); - } - } - afb_req_unref(memo->request); - free(memo); -} - -static void embed_call_void(struct afb_req request, const char *method) -{ - struct memo *memo = make_memo(request, method); - if (memo == NULL) - afb_req_fail(request, "failed", "out of memory"); - else if (jbus_call_sj(jbus, method, "true", (void*)embed_call_void_callback, memo) < 0) { - afb_req_fail(request, "failed", "dbus failure"); - free(memo); - } -} - -static void call_appid_callback(int status, struct json_object *obj, struct memo *memo) -{ - if (afb_interface->verbosity) - fprintf(stderr, "(afm-main-plugin) %s -> %s\n", memo->method, - obj ? json_object_to_json_string(obj) : "NULL"); - if (obj == NULL) { - afb_req_fail(memo->request, "failed", "framework daemon failure"); - } else { - obj = json_object_get(obj); - afb_req_success(memo->request, obj, NULL); - } - afb_req_unref(memo->request); - free(memo); -} - -static void call_appid(struct afb_req request, const char *method) -{ - struct memo *memo; - char *sid; - const char *id = afb_req_value(request, _id_); - if (id == NULL) { - afb_req_fail(request, "bad-request", "missing 'id'"); - return; - } - memo = make_memo(request, method); - if (asprintf(&sid, "\"%s\"", id) <= 0 || memo == NULL) { - afb_req_fail(request, "server-error", "out of memory"); - free(memo); - return; - } - if (jbus_call_sj(jbus, method, sid, (void*)call_appid_callback, memo) < 0) { - afb_req_fail(request, "failed", "dbus failure"); - free(memo); - } - free(sid); -} - -static void call_runid(struct afb_req request, const char *method) -{ - struct json_object *obj; - const char *id = afb_req_value(request, _runid_); - if (id == NULL) { - afb_req_fail(request, "bad-request", "missing 'runid'"); - return; - } - obj = jbus_call_sj_sync(jbus, method, id); - if (afb_interface->verbosity) - fprintf(stderr, "(afm-main-plugin) %s(%s) -> %s\n", method, id, - obj ? json_object_to_json_string(obj) : "NULL"); - if (obj == NULL) { - afb_req_fail(request, "failed", "framework daemon failure"); - return; - } - obj = json_object_get(obj); - afb_req_success(request, obj, NULL); -} - -/************************** entries ******************************/ - -static void runnables(struct afb_req request) -{ - embed_call_void(request, _runnables_); -} - -static void detail(struct afb_req request) -{ - call_appid(request, _detail_); -} - -static void start(struct afb_req request) -{ - struct json_object *obj; - const char *id, *mode; - char *query; - int rc; - - /* get the id */ - id = afb_req_value(request, _id_); - if (id == NULL) { - afb_req_fail(request, "bad-request", "missing 'id'"); - return; - } - /* get the mode */ - mode = afb_req_value(request, _mode_); - if (mode == NULL || !strcmp(mode, _auto_)) { - mode = afb_interface->mode == AFB_MODE_REMOTE ? _remote_ : _local_; - } - - /* create the query */ - rc = asprintf(&query, "{\"id\":\"%s\",\"mode\":\"%s\"}", id, mode); - if (rc < 0) { - afb_req_fail(request, "server-error", "out of memory"); - return; - } - - /* calls the service */ - obj = jbus_call_sj_sync(jbus, _start_, query); - if (afb_interface->verbosity) - fprintf(stderr, "(afm-main-plugin) start(%s) -> %s\n", query, - obj ? json_object_to_json_string(obj) : "NULL"); - free(query); - - /* check status */ - obj = json_object_get(obj); - if (obj == NULL) { - afb_req_fail(request, "failed", "framework daemon failure"); - return; - } - - /* embed if needed */ - if (json_object_get_type(obj) == json_type_int) - obj = embed(_runid_, obj); - afb_req_success(request, obj, NULL); -} - -static void terminate(struct afb_req request) -{ - call_runid(request, _terminate_); -} - -static void stop(struct afb_req request) -{ - call_runid(request, _stop_); -} - -static void continue_(struct afb_req request) -{ - call_runid(request, _continue_); -} - -static void runners(struct afb_req request) -{ - embed_call_void(request, _runners_); -} - -static void state(struct afb_req request) -{ - call_runid(request, _state_); -} - -static void install(struct afb_req request) -{ - struct json_object *obj, *added; - char *query; - const char *filename; - struct afb_arg arg; - - /* get the argument */ - arg = afb_req_get(request, "widget"); - filename = arg.path; - if (filename == NULL) { - afb_req_fail(request, "bad-request", "missing 'widget' file"); - return; - } - - /* makes the query */ - if (0 >= asprintf(&query, "\"%s\"", filename)) { - afb_req_fail(request, "server-error", "out of memory"); - return; - } - - obj = jbus_call_sj_sync(jbus, _install_, query); - if (afb_interface->verbosity) - fprintf(stderr, "(afm-main-plugin) install(%s) -> %s\n", query, - obj ? json_object_to_json_string(obj) : "NULL"); - free(query); - - /* check status */ - if (obj == NULL) { - afb_req_fail(request, "failed", "framework daemon failure"); - return; - } - - /* embed if needed */ - if (json_object_object_get_ex(obj, _added_, &added)) - obj = added; - obj = json_object_get(obj); - obj = embed(_id_, obj); - afb_req_success(request, obj, NULL); -} - -static void uninstall(struct afb_req request) -{ - call_appid(request, _uninstall_); -} - -static const struct AFB_verb_desc_v1 verbs[] = -{ - {_runnables_, AFB_SESSION_CHECK, runnables, "Get list of runnable applications"}, - {_detail_ , AFB_SESSION_CHECK, detail, "Get the details for one application"}, - {_start_ , AFB_SESSION_CHECK, start, "Start an application"}, - {_terminate_, AFB_SESSION_CHECK, terminate, "Terminate a running application"}, - {_stop_ , AFB_SESSION_CHECK, stop, "Stop (pause) a running application"}, - {_continue_ , AFB_SESSION_CHECK, continue_, "Continue (resume) a stopped application"}, - {_runners_ , AFB_SESSION_CHECK, runners, "Get the list of running applications"}, - {_state_ , AFB_SESSION_CHECK, state, "Get the state of a running application"}, - {_install_ , AFB_SESSION_CHECK, install, "Install an application using a widget file"}, - {_uninstall_, AFB_SESSION_CHECK, uninstall, "Uninstall an application"}, - { NULL, 0, NULL, NULL } -}; - -static const struct AFB_plugin plug_desc = { - .type = AFB_PLUGIN_VERSION_1, - .v1 = { - .info = "Application Framework Master Service", - .prefix = "afm-main", - .verbs = verbs - } -}; - -const struct AFB_plugin *pluginAfbV1Register(const struct AFB_interface *itf) -{ - int rc; - struct sd_bus *sbus; - - /* records the interface */ - assert (afb_interface == NULL); - afb_interface = itf; - event_sender = afb_daemon_get_event_sender(itf->daemon); - - /* creates the jbus for accessing afm-user-daemon */ - sbus = afb_daemon_get_user_bus(itf->daemon); - if (sbus == NULL) - return NULL; - jbus = create_jbus(sbus, "/org/AGL/afm/user"); - if (jbus == NULL) - return NULL; - - /* records the signal handler */ - rc = jbus_on_signal_s(jbus, _changed_, application_list_changed, NULL); - if (rc < 0) { - jbus_unref(jbus); - return NULL; - } - - return &plug_desc; -} - diff --git a/plugins/afm-main-plugin/export.map b/plugins/afm-main-plugin/export.map deleted file mode 100644 index e2da85ca..00000000 --- a/plugins/afm-main-plugin/export.map +++ /dev/null @@ -1 +0,0 @@ -{ global: pluginAfbV1Register; local: *; }; diff --git a/plugins/afm-main-plugin/utils-jbus.c b/plugins/afm-main-plugin/utils-jbus.c deleted file mode 100644 index f339e0e6..00000000 --- a/plugins/afm-main-plugin/utils-jbus.c +++ /dev/null @@ -1,975 +0,0 @@ -/* - Copyright (C) 2015, 2016 "IoT.bzh" - - author: José Bollo <jose.bollo@iot.bzh> - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -#define _GNU_SOURCE - -#include <stdlib.h> -#include <stdio.h> -#include <errno.h> -#include <string.h> -#include <poll.h> -#include <assert.h> - -#include <json-c/json.h> -#include <systemd/sd-bus.h> -#include <systemd/sd-bus-protocol.h> - -#include "utils-jbus.h" - -/* - * max depth of json messages - */ -#define MAX_JSON_DEPTH 10 - -/* - * errors messages generated by jbus - */ -static const char out_of_memory_string[] = "out of memory"; - -/* - * structure for services - */ -struct jservice { - struct jservice *next; /* link to the next service */ - char *method; /* method name for the service */ - void (*oncall_s) (struct sd_bus_message *, const char *, void *); - /* string callback */ - void (*oncall_j) (struct sd_bus_message *, struct json_object *, void *); - /* json callback */ - void *data; /* closure data for the callbacks */ -}; - -/* - * structure for signals - */ -struct jsignal { - struct jsignal *next; /* link to the next signal */ - char *name; /* name of the expected signal */ - void (*onsignal_s) (const char *, void *); - /* string callback */ - void (*onsignal_j) (struct json_object *, void *); - /* json callback */ - void *data; /* closure data for the callbacks */ -}; - -/* - * structure for asynchronous requests - */ -struct jrespw { - struct jbus *jbus; - void (*onresp_s) (int, const char *, void *); - /* string callback */ - void (*onresp_j) (int, struct json_object *, void *); - /* json callback */ - void *data; /* closure data for the callbacks */ -}; - -/* - * structure for handling either client or server jbus on dbus - */ -struct jbus { - int refcount; /* referenced how many time */ - struct sd_bus *sdbus; - struct sd_bus_slot *sservice; - struct sd_bus_slot *ssignal; - struct json_tokener *tokener; /* string to json tokenizer */ - struct jservice *services; /* first service */ - struct jsignal *signals; /* first signal */ - char *path; /* dbus path */ - char *name; /* dbus name */ -}; - -/*********************** STATIC COMMON METHODS *****************/ - -static int mkerrno(int rc) -{ - if (rc >= 0) - return rc; - errno = -rc; - return -1; -} - -/* - * Replies the error "out of memory". - * This function is intended to be used in services when an - * allocation fails. Thus, it set errno to ENOMEM and - * returns -1. - */ -static inline int reply_out_of_memory(struct sd_bus_message *smsg) -{ - jbus_reply_error_s(smsg, out_of_memory_string); - errno = ENOMEM; - return -1; -} - -/* - * Parses the json-string 'msg' to create a json object stored - * in 'obj'. It uses the tokener of 'jbus'. This is a small - * improvement to avoid recreation of tokeners. - * - * Returns 1 in case of success and put the result in *'obj'. - * Returns 0 in case of error and put NULL in *'obj'. - */ -static int jparse(struct jbus *jbus, const char *msg, struct json_object **obj) -{ - json_tokener_reset(jbus->tokener); - *obj = json_tokener_parse_ex(jbus->tokener, msg, -1); - if (json_tokener_get_error(jbus->tokener) == json_tokener_success) - return 1; - json_object_put(*obj); - *obj = NULL; - return 0; -} - -static int on_service_call(struct sd_bus_message *smsg, struct jbus *jbus, sd_bus_error *error) -{ - struct jservice *service; - const char *member, *content; - struct json_object *obj; - - /* check the type */ - if (!sd_bus_message_has_signature(smsg, "s") - || sd_bus_message_read_basic(smsg, 's', &content) < 0) { - sd_bus_error_set_const(error, "bad signature", ""); - return 1; - } - - /* dispatch */ - member = sd_bus_message_get_member(smsg); - service = jbus->services; - while (service != NULL) { - if (!strcmp(service->method, member)) { - sd_bus_message_ref(smsg); - if (service->oncall_s) - service->oncall_s(smsg, content, service->data); - else if (service->oncall_j) { - if (!jparse(jbus, content, &obj)) - obj = json_object_new_string(content); - service->oncall_j(smsg, obj, service->data); - json_object_put(obj); - } - return 1; - } - service = service->next; - } - return 0; -} - -/* - * Adds to 'jbus' a service of name 'method'. The service is - * performed by one of the callback 'oncall_s' (for string) or - * 'oncall_j' (for json) that will receive the request and the - * closure parameter 'data'. - * - * returns 0 in case of success or -1 in case of error (ENOMEM). - */ -static int add_service( - struct jbus *jbus, - const char *method, - void (*oncall_s) (struct sd_bus_message *, const char *, void *), - void (*oncall_j) (struct sd_bus_message *, struct json_object *, void *), - void *data) -{ - int rc; - struct jservice *srv; - - /* connection of the service */ - if (jbus->sservice == NULL) { - rc = sd_bus_add_object(jbus->sdbus, &jbus->sservice, jbus->path, (void*)on_service_call, jbus); - if (rc < 0) { - errno = -rc; - goto error; - } - } - - /* allocation */ - srv = malloc(sizeof *srv); - if (srv == NULL) { - errno = ENOMEM; - goto error; - } - srv->method = strdup(method); - if (!srv->method) { - errno = ENOMEM; - goto error2; - } - - /* record the service */ - srv->oncall_s = oncall_s; - srv->oncall_j = oncall_j; - srv->data = data; - srv->next = jbus->services; - jbus->services = srv; - - return 0; - - error2: - free(srv); - error: - return -1; -} - -static int on_signal_event(struct sd_bus_message *smsg, struct jbus *jbus, sd_bus_error *error) -{ - struct jsignal *signal; - const char *member, *content; - struct json_object *obj; - - /* check the type */ - if (!sd_bus_message_has_signature(smsg, "s") - || sd_bus_message_read_basic(smsg, 's', &content) < 0) - return 0; - - /* dispatch */ - member = sd_bus_message_get_member(smsg); - signal = jbus->signals; - while (signal != NULL) { - if (!strcmp(signal->name, member)) { - if (signal->onsignal_s) - signal->onsignal_s(content, signal->data); - else if (signal->onsignal_j) { - if (!jparse(jbus, content, &obj)) - obj = json_object_new_string(content); - signal->onsignal_j(obj, signal->data); - json_object_put(obj); - } - } - signal = signal->next; - } - return 0; -} - -/* - * Adds to 'jbus' a handler for the signal of 'name' emmited by - * the sender and the interface that 'jbus' is linked to. - * The signal is handled by one of the callback 'onsignal_s' - * (for string) or 'onsignal_j' (for json) that will receive - * parameters associated with the signal and the closure - * parameter 'data'. - * - * returns 0 in case of success or -1 in case of error (ENOMEM). - */ -static int add_signal( - struct jbus *jbus, - const char *name, - void (*onsignal_s) (const char *, void *), - void (*onsignal_j) (struct json_object *, void *), - void *data) -{ - int rc; - struct jsignal *sig; - char *match; - - /* connection of the signal */ - if (jbus->ssignal == NULL) { - rc = asprintf(&match, "type='signal',path='%s',interface='%s'", jbus->path, jbus->name); - if (rc < 0) { - errno = ENOMEM; - goto error; - } - rc = sd_bus_add_match(jbus->sdbus, &jbus->ssignal, match, (void*)on_signal_event, jbus); - free(match); - if (rc < 0) { - errno = -rc; - goto error; - } - } - - /* allocation */ - sig = malloc(sizeof *sig); - if (sig == NULL) { - errno = ENOMEM; - goto error; - } - sig->name = strdup(name); - if (!sig->name) { - errno = ENOMEM; - goto error2; - } - - /* record the signal */ - sig->onsignal_s = onsignal_s; - sig->onsignal_j = onsignal_j; - sig->data = data; - sig->next = jbus->signals; - jbus->signals = sig; - - return 0; - - error2: - free(sig); - error: - return -1; -} - -static int on_reply(struct sd_bus_message *smsg, struct jrespw *jrespw, sd_bus_error *error) -{ - struct json_object *obj; - const char *reply; - int iserror; - - /* check the type */ - if (!sd_bus_message_has_signature(smsg, "s") - || sd_bus_message_read_basic(smsg, 's', &reply) < 0) { - sd_bus_error_set_const(error, "bad signature", ""); - goto end; - } - iserror = sd_bus_message_is_method_error(smsg, NULL); - - /* dispatch string? */ - if (jrespw->onresp_s != NULL) { - jrespw->onresp_s(iserror, reply, jrespw->data); - goto end; - } - - /* dispatch json */ - if (!jparse(jrespw->jbus, reply, &obj)) - obj = json_object_new_string(reply); - jrespw->onresp_j(iserror, obj, jrespw->data); - json_object_put(obj); - - end: - free(jrespw); - return 1; -} - -/* - * Creates a message for 'method' with one string parameter being 'query' - * and sends it to the destination, object and interface linked to 'jbus'. - * - * Adds to 'jbus' the response handler defined by the callbacks 'onresp_s' - * (for string) and 'onresp_j' (for json) and the closure parameter 'data'. - * - * Returns 0 in case of success or -1 in case of error. - */ -static int call( - struct jbus *jbus, - const char *method, - const char *query, - void (*onresp_s) (int, const char *, void *), - void (*onresp_j) (int, struct json_object *, void *), - void *data) -{ - int rc; - struct jrespw *resp; - - /* allocates the response structure */ - resp = malloc(sizeof *resp); - if (resp == NULL) { - errno = ENOMEM; - goto error; - } - - /* fulfill the response structure */ - resp->jbus = jbus; - resp->onresp_s = onresp_s; - resp->onresp_j = onresp_j; - resp->data = data; - - rc = sd_bus_call_method_async(jbus->sdbus, NULL, jbus->name, jbus->path, jbus->name, method, (void*)on_reply, resp, "s", query); - if (rc < 0) { - errno = -rc; - goto error2; - } - - return 0; - - error2: - free(resp); - error: - return -1; -} - -/********************* MAIN FUNCTIONS *****************************************/ - -/* - * Creates a 'jbus' bound the 'path' and it derived names and linked - * either to the DBUS SYSTEM when 'session' is nul or to the DBUS SESSION - * if 'session' is not nul. - * - * The parameter 'path' is intended to be the path of a DBUS single object. - * Single means that it exists only one instance of the object on the - * given bus. That path implies 2 derived DBUS names: - * 1. the destination name of the program that handles the object - * 2. the interface name of the object - * These names are derived by removing the heading slash (/) and - * by replacing all occurences of slashes by dots. - * For example, passing path = /a/b/c means that the object /a/b/c is - * handled by the destination a.b.c and replies to the interface a.b.c - * - * Returns the created jbus or NULL in case of error. - */ -struct jbus *create_jbus(struct sd_bus *sdbus, const char *path) -{ - struct jbus *jbus; - char *name; - - /* create the jbus object */ - jbus = calloc(1, sizeof *jbus); - if (jbus == NULL) { - errno = ENOMEM; - goto error; - } - jbus->refcount = 1; - - /* create the tokener */ - jbus->tokener = json_tokener_new_ex(MAX_JSON_DEPTH); - if (jbus->tokener == NULL) { - errno = ENOMEM; - goto error2; - } - - /* records the path */ - jbus->path = strdup(path); - if (jbus->path == NULL) { - errno = ENOMEM; - goto error2; - } - - /* makes the name from the path */ - while (*path == '/') - path++; - jbus->name = name = strdup(path); - if (name == NULL) { - errno = ENOMEM; - goto error2; - } - while (*name) { - if (*name == '/') - *name = '.'; - name++; - } - name--; - while (name >= jbus->name && *name == '.') - *name-- = 0; - if (!*jbus->name) { - errno = EINVAL; - goto error2; - } - - /* connect and init */ - jbus->sdbus = sd_bus_ref(sdbus); - - return jbus; - - error2: - jbus_unref(jbus); - error: - return NULL; -} - -/* - * Adds one reference to 'jbus'. - */ -void jbus_addref(struct jbus *jbus) -{ - jbus->refcount++; -} - -/* - * Removes one reference to 'jbus'. Destroys 'jbus' and it related - * data if the count of references decrease to zero. - */ -void jbus_unref(struct jbus *jbus) -{ - struct jservice *srv; - struct jsignal *sig; - if (!--jbus->refcount) { - while ((srv = jbus->services) != NULL) { - jbus->services = srv->next; - free(srv->method); - free(srv); - } - while ((sig = jbus->signals) != NULL) { - jbus->signals = sig->next; - free(sig->name); - free(sig); - } - if (jbus->sservice != NULL) - sd_bus_slot_unref(jbus->sservice); - if (jbus->ssignal != NULL) - sd_bus_slot_unref(jbus->ssignal); - if (jbus->tokener != NULL) - json_tokener_free(jbus->tokener); - sd_bus_unref(jbus->sdbus); - free(jbus->name); - free(jbus->path); - free(jbus); - } -} - -/* - * Replies an error of string 'error' to the request handled by 'smsg'. - * Also destroys the request 'smsg' that must not be used later. - * - * Returns 0 in case of success or -1 in case of error. - */ -int jbus_reply_error_s(struct sd_bus_message *smsg, const char *error) -{ - int rc = sd_bus_reply_method_errorf(smsg, SD_BUS_ERROR_FAILED, "%s", error); - sd_bus_message_unref(smsg); - return mkerrno(rc); -} - -/* - * Replies an error of json 'reply' to the request handled by 'smsg'. - * Also destroys the request 'smsg' that must not be used later. - * - * Returns 0 in case of success or -1 in case of error. - */ -int jbus_reply_error_j(struct sd_bus_message *smsg, struct json_object *reply) -{ - const char *str = json_object_to_json_string(reply); - return str ? jbus_reply_error_s(smsg, str) : reply_out_of_memory(smsg); -} - -/* - * Replies normally the string 'reply' to the request handled by 'smsg'. - * Also destroys the request 'smsg' that must not be used later. - * - * Returns 0 in case of success or -1 in case of error. - */ -int jbus_reply_s(struct sd_bus_message *smsg, const char *reply) -{ - int rc = sd_bus_reply_method_return(smsg, "s", reply); - sd_bus_message_unref(smsg); - return mkerrno(rc); -} - -/* - * Replies normally the json 'reply' to the request handled by 'smsg'. - * Also destroys the request 'smsg' that must not be used later. - * - * Returns 0 in case of success or -1 in case of error. - */ -int jbus_reply_j(struct sd_bus_message *smsg, struct json_object *reply) -{ - const char *str = json_object_to_json_string(reply); - return str ? jbus_reply_s(smsg, str) : reply_out_of_memory(smsg); -} - -/* - * Sends from 'jbus' the signal of 'name' handling the string 'content'. - * - * Returns 0 in case of success or -1 in case of error. - */ -int jbus_send_signal_s(struct jbus *jbus, const char *name, const char *content) -{ - return mkerrno(sd_bus_emit_signal(jbus->sdbus, jbus->path, jbus->name, name, "s", content)); -} - -/* - * Sends from 'jbus' the signal of 'name' handling the json 'content'. - * - * Returns 0 in case of success or -1 in case of error. - */ -int jbus_send_signal_j(struct jbus *jbus, const char *name, - struct json_object *content) -{ - const char *str = json_object_to_json_string(content); - if (str == NULL) { - errno = ENOMEM; - return -1; - } - return jbus_send_signal_s(jbus, name, str); -} - -/* - * Adds to 'jbus' a service handling calls to the 'method' using - * the "string" callback 'oncall' and the closure value 'data'. - * - * The callback 'oncall' is invoked for handling incoming method - * calls. It receives 3 parameters: - * 1. struct sd_bus_message *: a handler to data to be used for replying - * 2. const char *: the received string - * 3. void *: the closure 'data' set by this function - * - * Returns 0 in case of success or -1 in case of error. - */ -int jbus_add_service_s( - struct jbus *jbus, - const char *method, - void (*oncall) (struct sd_bus_message *, const char *, void *), - void *data) -{ - return add_service(jbus, method, oncall, NULL, data); -} - -/* - * Adds to 'jbus' a service handling calls to the 'method' using - * the "json" callback 'oncall' and the closure value 'data'. - * - * The callback 'oncall' is invoked for handling incoming method - * calls. It receives 3 parameters: - * 1. struct sd_bus_message *: a handler to data to be used for replying - * 2. struct json_object *: the received json - * 3. void *: the closure 'data' set by this function - * - * Returns 0 in case of success or -1 in case of error. - */ -int jbus_add_service_j( - struct jbus *jbus, - const char *method, - void (*oncall) (struct sd_bus_message *, struct json_object *, void *), - void *data) -{ - return add_service(jbus, method, NULL, oncall, data); -} - -/* - * Start to serve: activate services declared for 'jbus'. - * This function, in fact, declares 'jbus' as the receiver - * for calls to the destination derived from the path set at - * 'jbus' creation. - * It also allows 'jbus' to emit signals of that origin. - * - * Returns 0 in case of success or -1 in case of error. - */ -int jbus_start_serving(struct jbus *jbus) -{ - return mkerrno(sd_bus_request_name(jbus->sdbus, jbus->name, 0)); -} - -/* - * Asynchronous call to 'method' of 'jbus' passing the string 'query'. - * On response, the function 'onresp' is called with the returned string - * value and the closure 'data'. - * The function 'onresp' is invoked with 3 parameters: - * 1. int: 0 if no error or -1 if error. - * 2. const char *: the returned string (might be NULL if error) - * 3. void *: the closure 'data' - * - * Returns 0 in case of success or -1 in case of error. - */ -int jbus_call_ss( - struct jbus *jbus, - const char *method, - const char *query, - void (*onresp) (int, const char *, void *), - void *data) -{ - return call(jbus, method, query, onresp, NULL, data); -} - -/* - * Asynchronous call to 'method' of 'jbus' passing the string 'query'. - * On response, the function 'onresp' is called with the returned json - * value and the closure 'data'. - * The function 'onresp' is invoked with 3 parameters: - * 1. int: 0 if no error or -1 if error. - * 2. const char *: the returned json (might be NULL if error) - * 3. void *: the closure 'data' - * - * Returns 0 in case of success or -1 in case of error. - */ -int jbus_call_sj( - struct jbus *jbus, - const char *method, - const char *query, - void (*onresp) (int, struct json_object *, void *), - void *data) -{ - return call(jbus, method, query, NULL, onresp, data); -} - -/* - * Asynchronous call to 'method' of 'jbus' passing the json 'query'. - * On response, the function 'onresp' is called with the returned string - * value and the closure 'data'. - * The function 'onresp' is invoked with 3 parameters: - * 1. int: 0 if no error or -1 if error. - * 2. const char *: the returned string (might be NULL if error) - * 3. void *: the closure 'data' - * - * Returns 0 in case of success or -1 in case of error. - */ -int jbus_call_js( - struct jbus *jbus, - const char *method, - struct json_object *query, - void (*onresp) (int, const char *, void *), - void *data) -{ - const char *str = json_object_to_json_string(query); - if (str == NULL) { - errno = ENOMEM; - return -1; - } - return call(jbus, method, str, onresp, NULL, data); -} - -/* - * Asynchronous call to 'method' of 'jbus' passing the json 'query'. - * On response, the function 'onresp' is called with the returned json - * value and the closure 'data'. - * The function 'onresp' is invoked with 3 parameters: - * 1. int: 0 if no error or -1 if error. - * 2. const char *: the returned json (might be NULL if error) - * 3. void *: the closure 'data' - * - * Returns 0 in case of success or -1 in case of error. - */ -int jbus_call_jj( - struct jbus *jbus, - const char *method, - struct json_object *query, - void (*onresp) (int, struct json_object *, void *), - void *data) -{ - const char *str = json_object_to_json_string(query); - if (str == NULL) { - errno = ENOMEM; - return -1; - } - return call(jbus, method, str, NULL, onresp, data); -} - -/* - * Synchronous call to 'method' of 'jbus' passing the string 'query'. - * The returned string response is returned. - * - * Returns the string response or NULL in case of error. - */ -char *jbus_call_ss_sync( - struct jbus *jbus, - const char *method, - const char *query) -{ - sd_bus_message *smsg = NULL; - sd_bus_error error = SD_BUS_ERROR_NULL; - char *result = NULL; - const char *reply; - - /* makes the call */ - if (mkerrno(sd_bus_call_method(jbus->sdbus, jbus->name, jbus->path, jbus->name, method, &error, &smsg, "s", query)) < 0) - goto error; - - /* check if error */ - if (sd_bus_message_is_method_error(smsg, NULL)) - goto error; - - /* check the returned type */ - if (!sd_bus_message_has_signature(smsg, "s") - || sd_bus_message_read_basic(smsg, 's', &reply) < 0) - goto error; - - /* get the result */ - result = strdup(reply); - -error: - sd_bus_message_unref(smsg); - sd_bus_error_free(&error); - return result; -} - -/* - * Synchronous call to 'method' of 'jbus' passing the string 'query'. - * The returned json response is returned. - * - * Returns the json response or NULL in case of error. - */ -struct json_object *jbus_call_sj_sync( - struct jbus *jbus, - const char *method, - const char *query) -{ - struct json_object *obj; - char *str = jbus_call_ss_sync(jbus, method, query); - if (str == NULL) - obj = NULL; - else { - jparse(jbus, str, &obj); - free(str); - } - return obj; -} - -/* - * Synchronous call to 'method' of 'jbus' passing the json 'query'. - * The returned string response is returned. - * - * Returns the string response or NULL in case of error. - */ -char *jbus_call_js_sync( - struct jbus *jbus, - const char *method, - struct json_object *query) -{ - const char *str = json_object_to_json_string(query); - if (str == NULL) { - errno = ENOMEM; - return NULL; - } - return jbus_call_ss_sync(jbus, method, str); -} - -/* - * Synchronous call to 'method' of 'jbus' passing the json 'query'. - * The returned json response is returned. - * - * Returns the json response or NULL in case of error. - */ -struct json_object *jbus_call_jj_sync( - struct jbus *jbus, - const char *method, - struct json_object *query) -{ - const char *str = json_object_to_json_string(query); - if (str == NULL) { - errno = ENOMEM; - return NULL; - } - return jbus_call_sj_sync(jbus, method, str); -} - -/* - * Records for 'jbus' the string signal handler 'onsig' with closure 'data' - * for the signal of 'name'. - * The callback handler is called with 2 arguments: - * 1. char *: the string parameter associated to the signal - * 2. void *: the closure data. - * - * Returns 0 in case of success or -1 otherwise. - */ -int jbus_on_signal_s( - struct jbus *jbus, - const char *name, - void (*onsig) (const char *, void *), - void *data) -{ - return add_signal(jbus, name, onsig, NULL, data); -} - -/* - * Records for 'jbus' the json signal handler 'onsig' with closure 'data' - * for the signal of 'name'. - * The callback handler is called with 2 arguments: - * 1. struct json_object *: the json parameter associated to the signal - * 2. void *: the closure data. - * - * Returns 0 in case of success or -1 otherwise. - */ -int jbus_on_signal_j( - struct jbus *jbus, - const char *name, - void (*onsig) (struct json_object *, void *), - void *data) -{ - return add_signal(jbus, name, NULL, onsig, data); -} - -/****************** FEW LITTLE TESTS *****************************************/ - -#if defined(SERVER)||defined(CLIENT) -#include <stdio.h> -#include <unistd.h> - -static struct sd_bus *msbus() -{ - static struct sd_bus *r = NULL; - if (r == NULL) { - static sd_event *e; - sd_event_default(&e); - sd_bus_open_user(&r); - sd_bus_attach_event(r, e, 0); - } - return r; -} - -static sd_event *events() -{ - static sd_event *ev = NULL; - if (ev == NULL) - ev = sd_bus_get_event(msbus()); - return ev; -} - -static int mwait(int timeout, void *closure) -{ - sd_event_run(events(), -1); - return 0; -} - -static struct jbus *jbus; - -#ifdef SERVER -void ping(struct sd_bus_message *smsg, struct json_object *request, void *unused) -{ - printf("ping(%s) -> %s\n", json_object_to_json_string(request), - json_object_to_json_string(request)); - jbus_reply_j(smsg, request); - json_object_put(request); -} - -void incr(struct sd_bus_message *smsg, struct json_object *request, void *unused) -{ - static int counter = 0; - struct json_object *res = json_object_new_int(++counter); - printf("incr(%s) -> %s\n", json_object_to_json_string(request), - json_object_to_json_string(res)); - jbus_reply_j(smsg, res); - jbus_send_signal_j(jbus, "incremented", res); - json_object_put(res); - json_object_put(request); -} - -int main() -{ - int s1, s2, s3; - jbus = create_jbus(msbus(), "/bzh/iot/jdbus"); - s1 = jbus_add_service_j(jbus, "ping", ping, NULL); - s2 = jbus_add_service_j(jbus, "incr", incr, NULL); - s3 = jbus_start_serving(jbus); - printf("started %d %d %d\n", s1, s2, s3); - while (!mwait(-1,jbus)) ; - return 0; -} -#endif - -#ifdef CLIENT -void onresp(int status, struct json_object *response, void *data) -{ - printf("resp: %d, %s, %s\n", status, (char *)data, - json_object_to_json_string(response)); - json_object_put(response); -} - -void signaled(const char *content, void *data) -{ - printf("signaled with {%s}/%s\n", content, (char*)data); -} - -int main() -{ - int i = 1; - jbus = create_jbus(msbus(), "/bzh/iot/jdbus"); - jbus_on_signal_s(jbus, "incremented", signaled, "closure-signal"); - while (i--) { - jbus_call_sj(jbus, "ping", "{\"toto\":[1,2,3,4,true,\"toto\"]}", - onresp, "ping"); - jbus_call_sj(jbus, "incr", "{\"doit\":\"for-me\"}", onresp, - "incr"); - mwait(-1,jbus); - } - printf("[[[%s]]]\n", - jbus_call_ss_sync(jbus, "ping", "\"formidable!\"")); - while (!mwait(-1,jbus)) ; - return 0; -} -#endif -#endif - diff --git a/plugins/afm-main-plugin/utils-jbus.h b/plugins/afm-main-plugin/utils-jbus.h deleted file mode 100644 index 44b84c18..00000000 --- a/plugins/afm-main-plugin/utils-jbus.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - Copyright (C) 2015, 2016 "IoT.bzh" - - author: José Bollo <jose.bollo@iot.bzh> - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -#pragma once - -struct sd_bus; - -struct sd_bus_message; -struct jbus; - -extern struct jbus *create_jbus(struct sd_bus *sdbus, const char *path); - -extern void jbus_addref(struct jbus *jbus); -extern void jbus_unref(struct jbus *jbus); - -/* verbs for the clients */ -extern int jbus_call_ss( - struct jbus *jbus, - const char *method, - const char *query, - void (*onresp) (int, const char *, void *), - void *data); - -extern int jbus_call_js( - struct jbus *jbus, - const char *method, - struct json_object *query, - void (*onresp) (int, const char *, void *), - void *data); - -extern int jbus_call_sj( - struct jbus *jbus, - const char *method, - const char *query, - void (*onresp) (int, struct json_object *, void *), - void *data); - -extern int jbus_call_jj( - struct jbus *jbus, - const char *method, - struct json_object *query, - void (*onresp) (int, struct json_object *, void *), - void *data); - -extern char *jbus_call_ss_sync( - struct jbus *jbus, - const char *method, - const char *query); - -extern char *jbus_call_js_sync( - struct jbus *jbus, - const char *method, - struct json_object *query); - -extern struct json_object *jbus_call_sj_sync( - struct jbus *jbus, - const char *method, - const char *query); - -extern struct json_object *jbus_call_jj_sync( - struct jbus *jbus, - const char *method, - struct json_object *query); - -extern int jbus_on_signal_s( - struct jbus *jbus, - const char *name, - void (*onsignal) (const char *, void *), - void *data); - -extern int jbus_on_signal_j( - struct jbus *jbus, - const char *name, - void (*onsignal) (struct json_object *, void *), - void *data); - -/* verbs for servers */ -extern int jbus_reply_s( - struct sd_bus_message *smsg, - const char *reply); - -extern int jbus_reply_j( - struct sd_bus_message *smsg, - struct json_object *reply); - -extern int jbus_reply_error_s( - struct sd_bus_message *smsg, - const char *reply); - -extern int jbus_reply_error_j( - struct sd_bus_message *smsg, - struct json_object *reply); - -extern int jbus_add_service_s( - struct jbus *jbus, - const char *method, - void (*oncall) (struct sd_bus_message *, const char *, void *), - void *data); - -extern int jbus_add_service_j( - struct jbus *jbus, - const char *method, - void (*oncall) (struct sd_bus_message *, struct json_object *, void *), - void *data); - -extern int jbus_start_serving( - struct jbus *jbus); - -extern int jbus_send_signal_s( - struct jbus *jbus, - const char *name, - const char *content); - -extern int jbus_send_signal_j( - struct jbus *jbus, - const char *name, - struct json_object *content); - |