diff options
Diffstat (limited to 'plugins/afm-main-plugin/utils-sbus.c')
-rw-r--r-- | plugins/afm-main-plugin/utils-sbus.c | 1037 |
1 files changed, 0 insertions, 1037 deletions
diff --git a/plugins/afm-main-plugin/utils-sbus.c b/plugins/afm-main-plugin/utils-sbus.c deleted file mode 100644 index a5c63c65..00000000 --- a/plugins/afm-main-plugin/utils-sbus.c +++ /dev/null @@ -1,1037 +0,0 @@ -/* - Copyright 2015 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 <dbus/dbus.h> - -#include "utils-sbus.h" - -/* - * errors messages generated by sbus - */ -static const char invalid_request_string[] = "invalid request"; -static const char out_of_memory_string[] = "out of memory"; - -/* - * structure for handled messages - */ -struct sbusmsg { - DBusMessage *message; /* message of the message */ - DBusConnection *connection; /* connection of the message */ -}; - -/* - * structure for services - */ -struct sbus_service { - struct sbus_service *next; /* link to the next service */ - char *destination; /* destination for the service */ - char *path; /* path for the service */ - char *iface; /* iface for the service */ - char *member; /* member for the service */ - void (*oncall) (struct sbusmsg *, const char *, void *); - /* callback */ - void *closure; /* closure for the callbacks */ -}; - -/* - * structure for signals - */ -struct sbus_signal { - struct sbus_signal *next; /* link to the next signal */ - char *sender; /* expected sender of the signal */ - char *path; /* expected path of the signal */ - char *iface; /* expected iface of the signal */ - char *member; /* expected member of the signal */ - void (*onsignal) (const struct sbusmsg *, const char *, void *); - /* callback */ - void *closure; /* closure for the callbacks */ -}; - -/* - * structure for asynchronous requests (resp-onse w-aiter) - */ -struct srespw { - struct srespw *next; /* next asynchronous */ - dbus_uint32_t serial; /* serial dbus number */ - void *closure; /* closure for the callbacks */ - void (*onresp) (int, const char *, void *); - /* callback */ -}; - -/* - * structure for synchronous calls - */ -struct respsync { - int replied; /* boolean flag indicating reply */ - int status; /* received status */ - char *value; /* copy of the returned value */ -}; - -/* - * structure for handling either client or server sbus on dbus - */ -struct sbus { - int refcount; /* referenced how many time */ - DBusConnection *connection; /* connection to DBU */ - const struct sbus_itf *itf; /* interface to the main loop */ - void *itfclo; - struct sbus_service *services; /* first service */ - struct sbus_signal *signals; /* first signal */ - struct srespw *waiters; /* first response waiter */ - -}; - -static struct sbus system_sbus; -static struct sbus session_sbus; - -/*********************** STATIC COMMON METHODS *****************/ - -/* - * Frees the ressources attached to a message - */ -static inline void free_sbusmsg(struct sbusmsg *smsg) -{ - dbus_message_unref(smsg->message); - dbus_connection_unref(smsg->connection); - free(smsg); -} - -/* - * 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 sbusmsg *smsg) -{ - sbus_reply_error(smsg, out_of_memory_string); - errno = ENOMEM; - return -1; -} - -/* - * Checks if the incoming 'message' matches the interface - * linked to 'sbus'. - * - * Returns 1 if it matches or 0 wether it does not matches. - */ -/* -static int matchitf(struct sbus *sbus, DBusMessage * message) -{ - const char *itf = dbus_message_get_interface(message); - return itf != NULL && !strcmp(itf, sbus->name); -} -*/ - -/* - * Callback function for synchronous calls. - * This function fills the respsync structure pointed by 'data' - * with the copy of the answer. - */ -static void sync_of_replies(int status, const char *value, struct respsync *s) -{ - s->status = status; - s->value = status ? NULL : strdup(value ? value : ""); - s->replied = 1; -} - -/* - * Creates and returns the rule for 'signal'. - */ -static char *rule_of_signal(struct sbus_signal *signal) -{ - char *rule; - return asprintf(&rule, - "type='signal%s%s%s%s%s%s%s%s'", - signal->sender ? "',sender='" : "", - signal->sender ? signal->sender : "", - signal->path ? "',path='" : "", - signal->path ? signal->path : "", - signal->iface ? "',interface='" : "", - signal->iface ? signal->iface : "", - signal->member ? "',member='" : "", - signal->member ? signal->member : "" - ) < 0 ? NULL : rule; -} - -/*********************** STATIC DBUS MESSAGE HANDLING *****************/ - -/* - * Handles incomming responses 'message' on 'sbus'. Response are - * either expected if 'iserror' == 0 or errors if 'iserror' != 0. - * - * Returns DBUS_HANDLER_RESULT_HANDLED or DBUS_HANDLER_RESULT_NOT_YET_HANDLED - * as defined by the dbus function 'dbus_connection_add_filter'. - */ -static DBusHandlerResult incoming_resp( - struct sbus *sbus, - DBusMessage * message, - int iserror) -{ - int status; - const char *str; - struct srespw *jrw, **prv; - dbus_uint32_t serial; - - /* search for the waiter */ - serial = dbus_message_get_reply_serial(message); - prv = &sbus->waiters; - while ((jrw = *prv) != NULL) { - if (jrw->serial == serial) - goto found; - prv = &jrw->next; - } - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - /* treat it */ - found: - *prv = jrw->next; - if (jrw->onresp) { - /* retrieve the string value */ - if (dbus_message_get_args - (message, NULL, DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID)) - status = 0; - else { - status = -1; - str = NULL; - } - /* call now */ - jrw->onresp(iserror ? -1 : status, str, jrw->closure); - } - free(jrw); - return DBUS_HANDLER_RESULT_HANDLED; -} - -/* - * Handles incomming on 'sbus' method calls for 'message'. - * - * Returns DBUS_HANDLER_RESULT_HANDLED or DBUS_HANDLER_RESULT_NOT_YET_HANDLED - * as defined by the dbus function 'dbus_connection_add_filter'. - */ -static DBusHandlerResult incoming_call( - struct sbus *sbus, - DBusMessage * message) -{ - struct sbus_service *service; - struct sbusmsg *smsg; - const char *str; - - /* search for the service */ - service = sbus->services; - while (service != NULL) { - if ((service->destination == NULL || !strcmp(service->destination, dbus_message_get_destination(message))) - && (service->path == NULL || !strcmp(service->path, dbus_message_get_path(message))) - && (service->iface == NULL || !strcmp(service->iface, dbus_message_get_interface(message))) - && (service->member == NULL || !strcmp(service->member, dbus_message_get_member(message)))) - goto found; - service = service->next; - } - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - found: - /* creates and init the smsg structure */ - smsg = malloc(sizeof *smsg); - if (smsg == NULL) - return DBUS_HANDLER_RESULT_NEED_MEMORY; - smsg->message = dbus_message_ref(message); - smsg->connection = dbus_connection_ref(sbus->connection); - - /* retrieve the string parameter of the message */ - if (!dbus_message_get_args - (message, NULL, DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID)) - goto invalid_request; - - /* handling strings only */ - service->oncall(smsg, str, service->closure); - return DBUS_HANDLER_RESULT_HANDLED; - -invalid_request: - sbus_reply_error(smsg, invalid_request_string); - return DBUS_HANDLER_RESULT_HANDLED; -} - -/* - * Handles incomming on 'sbus' signal propagated with 'message'. - * - * This is a design choice to ignore invalid signals. - * - * Returns DBUS_HANDLER_RESULT_HANDLED or DBUS_HANDLER_RESULT_NOT_YET_HANDLED - * as defined by the dbus function 'dbus_connection_add_filter'. - */ -static DBusHandlerResult incoming_signal( - struct sbus *sbus, - DBusMessage * message) -{ - DBusHandlerResult result; - struct sbus_signal *signal; - struct sbusmsg smsg; - const char *str; - - /* retrieve the string value */ - result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - if (!dbus_message_get_args(message, NULL, - DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID)) - goto end; - - /* search a handler */ - smsg.message = message; - smsg.connection = NULL; - signal = sbus->signals; - while (signal != NULL) { - if ((signal->path == NULL || !strcmp(signal->path, dbus_message_get_path(message))) - && (signal->iface == NULL || !strcmp(signal->iface, dbus_message_get_interface(message))) - && (signal->member == NULL || !strcmp(signal->member, dbus_message_get_member(message)))) { - signal->onsignal(&smsg, str, signal->closure); - result = DBUS_HANDLER_RESULT_HANDLED; - } - signal = signal->next; - } - end: - return result; -} - -/* - * Filters incomming messages as defined by the dbus function - * 'dbus_connection_add_filter'. - * Returns DBUS_HANDLER_RESULT_HANDLED or DBUS_HANDLER_RESULT_NOT_YET_HANDLED. - */ -static DBusHandlerResult incoming( - DBusConnection * connection, - DBusMessage * message, - struct sbus *sbus) -{ - switch (dbus_message_get_type(message)) { - case DBUS_MESSAGE_TYPE_METHOD_CALL: - return incoming_call(sbus, message); - case DBUS_MESSAGE_TYPE_METHOD_RETURN: - return incoming_resp(sbus, message, 0); - case DBUS_MESSAGE_TYPE_ERROR: - return incoming_resp(sbus, message, 1); - case DBUS_MESSAGE_TYPE_SIGNAL: - return incoming_signal(sbus, message); - } - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -/*********************** STATIC DBUS WATCH/POLLING INTERFACE **********/ - -struct swatch { - DBusConnection *connection; - DBusWatch *watch; - void *hndl; -}; - -static void on_hangup(struct swatch *s) -{ - dbus_watch_handle(s->watch, DBUS_WATCH_HANGUP); - while (dbus_connection_dispatch(s->connection) == DBUS_DISPATCH_DATA_REMAINS); -} - -static void on_readable(struct swatch *s) -{ - dbus_watch_handle(s->watch, DBUS_WATCH_READABLE); - while (dbus_connection_dispatch(s->connection) == DBUS_DISPATCH_DATA_REMAINS); -} - -static void on_writable(struct swatch *s) -{ - dbus_watch_handle(s->watch, DBUS_WATCH_WRITABLE); - while (dbus_connection_dispatch(s->connection) == DBUS_DISPATCH_DATA_REMAINS); -} - -/* - * DBUS Callback for removing a 'watch'. - * See function 'dbus_connection_set_watch_functions' - */ -static void watchdel(DBusWatch *watch, struct sbus *sbus) -{ - struct swatch *s = dbus_watch_get_data(watch); - sbus->itf->close(s->hndl); - free(s); -} - -/* - * DBUS Callback for changing a 'watch'. - * See function 'dbus_connection_set_watch_functions' - */ -static void watchtoggle(DBusWatch *watch, struct sbus *sbus) -{ - struct swatch *s = dbus_watch_get_data(watch); - int enabled = (int)dbus_watch_get_enabled(watch); - unsigned int flags = dbus_watch_get_flags(watch); - if (flags & DBUS_WATCH_READABLE) - sbus->itf->on_readable(s->hndl, enabled ? (void*)on_readable : NULL); - if (flags & DBUS_WATCH_WRITABLE) - sbus->itf->on_writable(s->hndl, enabled ? (void*)on_writable : NULL); -} - - -/* - * DBUS Callback for adding a 'watch'. - * See function 'dbus_connection_set_watch_functions' - */ -static dbus_bool_t watchadd(DBusWatch *watch, struct sbus *sbus) -{ - int fd; - struct swatch *s; - - s = malloc(sizeof *s); - if (s == NULL) - goto error; - fd = dbus_watch_get_unix_fd(watch); - s->hndl = sbus->itf->open(fd, s, sbus->itfclo); - if (s->hndl == NULL) - goto error2; - s->watch = watch; - s->connection = sbus->connection; - dbus_watch_set_data(watch, s, NULL); - sbus->itf->on_hangup(s->hndl, (void*)on_hangup); - watchtoggle(watch, sbus); - return TRUE; - error2: - free(s); - error: - return FALSE; -} - -/* - * Creates a 'sbus' 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 sbus or NULL in case of error. - */ -static struct sbus *get_sbus(const struct sbus_itf *itf, void *itfclo, struct sbus *sbus) -{ - /* create the sbus object */ - if (sbus->refcount > 0) { - if (itf != sbus->itf) - goto error; - goto success; - } - - /* connect and init */ - sbus->connection = dbus_bus_get(sbus == &session_sbus ? DBUS_BUS_SESSION - : DBUS_BUS_SYSTEM, NULL); - if (sbus->connection == NULL) - goto error; - - sbus->itf = itf; - sbus->itfclo = itfclo; - if (!dbus_connection_add_filter(sbus->connection, (void*)incoming, sbus, NULL) - || !dbus_connection_set_watch_functions(sbus->connection, (void*)watchadd, - (void*)watchdel, (void*)watchtoggle, sbus, NULL)) - goto error2; - - success: - sbus->refcount++; - return sbus; - - error2: - dbus_connection_unref(sbus->connection); - sbus->connection = NULL; - error: - return NULL; -} - -/********************* MAIN FUNCTIONS *****************************************/ - -/* - * Creates a 'sbus' bound to DBUS system using 'path' and returns it. - * See 'create_sbus' - */ -struct sbus *sbus_system(const struct sbus_itf *itf, void *itfclo) -{ - return get_sbus(itf, itfclo, &system_sbus); -} - -/* - * Creates a 'sbus' bound to DBUS session using 'path' and returns it. - * See 'create_sbus' - */ -struct sbus *sbus_session(const struct sbus_itf *itf, void *itfclo) -{ - return get_sbus(itf, itfclo, &session_sbus); -} - -/* - * Adds one reference to 'sbus'. - */ -void sbus_addref(struct sbus *sbus) -{ - sbus->refcount++; -} - -/* - * Removes one reference to 'sbus'. Destroys 'sbus' and it related - * data if the count of references decrease to zero. - */ -void sbus_unref(struct sbus *sbus) -{ - struct srespw *w; - if (!--sbus->refcount) { - while (sbus->services != NULL) - sbus_remove_service(sbus, sbus->services); - while (sbus->signals != NULL) - sbus_remove_signal(sbus, sbus->signals); - if (sbus->connection != NULL) { - dbus_connection_unref(sbus->connection); - sbus->connection = NULL; - } - while ((w = sbus->waiters)) { - sbus->waiters = w->next; - if (w->onresp) - w->onresp(-1, "cancelled", w->closure); - free(w); - } - } -} - -/* - * Sends from 'sbus' the signal of 'member' handling the string 'content'. - * - * Returns 0 in case of success or -1 in case of error. - */ -int sbus_send_signal(struct sbus *sbus, const char *sender, const char *path, const char *iface, const char *member, const char *content) -{ - int rc = -1; - DBusMessage *message; - - message = dbus_message_new_signal(path, iface, member); - if (message == NULL) - goto error; - - if (sender != NULL && !dbus_message_set_sender(message, sender)) - goto error2; - - if (!dbus_message_append_args(message, DBUS_TYPE_STRING, &content, - DBUS_TYPE_INVALID)) - goto error2; - - if (dbus_connection_send(sbus->connection, message, NULL)) - rc = 0; - - dbus_message_unref(message); - return rc; - - error2: - dbus_message_unref(message); - - error: - errno = ENOMEM; - return -1; -} - -/* - * Asynchronous call to 'method' of 'sbus' passing the string 'query'. - * On response, the function 'onresp' is called with the returned string - * value and the closure 'closure'. - * 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 'closure' - * - * Returns 0 in case of success or -1 in case of error. - */ -int sbus_call( - struct sbus *sbus, - const char *destination, - const char *path, - const char *iface, - const char *method, - const char *query, - void (*onresp) (int, const char *, void *), - void *closure) -{ - DBusMessage *msg; - struct srespw *resp; - - /* allocates the response structure */ - resp = malloc(sizeof *resp); - if (resp == NULL) { - errno = ENOMEM; - goto error; - } - - /* creates the message */ - msg = dbus_message_new_method_call(destination, path, iface, method); - if (msg == NULL) { - errno = ENOMEM; - goto error2; - } - - /* fill it */ - if (!dbus_message_append_args - (msg, DBUS_TYPE_STRING, &query, DBUS_TYPE_INVALID)) { - errno = ENOMEM; - goto error3; - } - - /* send it */ - if (!dbus_connection_send(sbus->connection, msg, &resp->serial)) { - /* TODO: which error? */ - goto error3; - } - - /* release the message that is not more used */ - dbus_message_unref(msg); - - /* fulfill the response structure */ - resp->closure = closure; - resp->onresp = onresp; - - /* links the response to list of reponse waiters */ - resp->next = sbus->waiters; - sbus->waiters = resp; - return 0; - - error3: - dbus_message_unref(msg); - error2: - free(resp); - error: - return -1; -} - -/* - * Synchronous call to 'method' of 'sbus' passing the string 'query'. - * The returned string response is returned. - * - * Returns the string response or NULL in case of error. - */ -char *sbus_call_sync( - struct sbus *sbus, - const char *destination, - const char *path, - const char *iface, - const char *method, - const char *query) -{ - struct respsync synchro; - synchro.value = NULL; - synchro.replied = sbus_call(sbus, destination, path, - iface, method, query, - (void*)sync_of_replies, &synchro); - while (!synchro.replied) - if (sbus->itf->wait(-1, sbus->itfclo) != 0) - return NULL; - return synchro.value; -} - - -/* - * Records for 'sbus' the string signal handler 'onsig' with closure 'closure' - * for the signal of 'member'. - * The callback handler is called with 2 arguments: - * 1. char *: the string parameter associated to the signal - * 2. void *: the closure closure. - * - * Returns 0 in case of success or -1 otherwise. - */ -struct sbus_signal *sbus_add_signal( - struct sbus *sbus, - const char *sender, - const char *path, - const char *iface, - const char *member, - void (*onsignal) (const struct sbusmsg *, const char *, void *), - void *closure) -{ - char *rule; - struct sbus_signal *signal; - - /* allocation */ - signal = calloc(1, sizeof *signal); - if (signal == NULL) - goto error; - if (sender != NULL) { - signal->sender = strdup(sender); - if (!signal->sender) - goto error2; - } - if (path != NULL) { - signal->path = strdup(path); - if (!signal->path) - goto error2; - } - if (iface != NULL) { - signal->iface = strdup(iface); - if (!signal->iface) - goto error2; - } - if (member != NULL) { - signal->member = strdup(member); - if (!signal->member) - goto error2; - } - - /* record the signal */ - rule = rule_of_signal(signal); - if (rule == NULL) - goto error2; - dbus_bus_add_match(sbus->connection, rule, NULL); - free(rule); - - /* record the signal */ - signal->onsignal = onsignal; - signal->closure = closure; - signal->next = sbus->signals; - sbus->signals = signal; - - return signal; - - error2: - free(signal->sender); - free(signal->path); - free(signal->iface); - free(signal->member); - free(signal); - error: - errno = ENOMEM; - return NULL; -} - -/* - * Removes the 'signal' handler from 'sbus' - * Returns 0 in case of success or -1 in case of error. - */ -int sbus_remove_signal(struct sbus *sbus, struct sbus_signal *signal) -{ - char *rule; - struct sbus_signal **it; - - it = &sbus->signals; - while (*it != NULL) { - if (*it == signal) - goto found; - it = &(*it)->next; - } - errno = EINVAL; - return -1; - -found: - rule = rule_of_signal(signal); - if (rule != NULL) { - dbus_bus_remove_match(sbus->connection, rule, NULL); - free(rule); - } - *it = signal->next; - free(signal->sender); - free(signal->path); - free(signal->iface); - free(signal->member); - free(signal); - return 0; -} - -/* - * Start to serve: activate services declared for 'sbus'. - * This function, in fact, declares 'sbus' as the receiver - * for calls to the destination derived from the path set at - * 'sbus' creation. - * It also allows 'sbus' to emit signals of that origin. - * - * Returns 0 in case of success or -1 in case of error. - */ -int sbus_add_name(struct sbus *sbus, const char *name) -{ - int status = dbus_bus_request_name(sbus->connection, name, - DBUS_NAME_FLAG_DO_NOT_QUEUE, NULL); - switch (status) { - case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER: - case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER: - return 0; - case DBUS_REQUEST_NAME_REPLY_EXISTS: - case DBUS_REQUEST_NAME_REPLY_IN_QUEUE: - default: - errno = EADDRINUSE; - return -1; - } -} - -/* - * Adds to 'sbus' a service handling calls to the 'method' using - * the callback 'oncall' and the closure value 'closure'. - * - * The callback 'oncall' is invoked for handling incoming method - * calls. It receives 3 parameters: - * 1. struct sbusmsg *: a handler to data to be used for replying - * 2. const char *: the received string - * 3. void *: the closure 'closure' set by this function - * - * Returns 0 in case of success or -1 in case of error. - */ -struct sbus_service *sbus_add_service( - struct sbus *sbus, - const char *destination, - const char *path, - const char *iface, - const char *member, - void (*oncall) (struct sbusmsg *, const char *, void *), - void *closure) -{ - struct sbus_service *service; - - /* allocation */ - service = calloc(1, sizeof *service); - if (service == NULL) - goto error; - if (destination != NULL) { - service->destination = strdup(destination); - if (!service->destination) - goto error2; - } - if (path != NULL) { - service->path = strdup(path); - if (!service->path) - goto error2; - } - if (iface != NULL) { - service->iface = strdup(iface); - if (!service->iface) - goto error2; - } - if (member != NULL) { - service->member = strdup(member); - if (!service->member) - goto error2; - } - - /* record the service */ - service->oncall = oncall; - service->closure = closure; - service->next = sbus->services; - sbus->services = service; - - return service; - - error2: - free(service->destination); - free(service->path); - free(service->iface); - free(service->member); - free(service); - error: - errno = ENOMEM; - return NULL; -} - -/* - * Removes the 'service' handler from 'sbus' - * Returns 0 in case of success or -1 in case of error. - */ -int sbus_remove_service(struct sbus *sbus, struct sbus_service *service) -{ - struct sbus_service **it; - - it = &sbus->services; - while (*it != NULL) { - if (*it == service) - goto found; - it = &(*it)->next; - } - errno = EINVAL; - return -1; - -found: - *it = service->next; - free(service->destination); - free(service->path); - free(service->iface); - free(service->member); - free(service); - return 0; -} - -const char *sbus_sender(const struct sbusmsg *smsg) -{ - return dbus_message_get_sender(smsg->message); -} - -const char *sbus_destination(const struct sbusmsg *smsg) -{ - return dbus_message_get_destination(smsg->message); -} - -const char *sbus_path(const struct sbusmsg *smsg) -{ - return dbus_message_get_path(smsg->message); -} - -const char *sbus_interface(const struct sbusmsg *smsg) -{ - return dbus_message_get_interface(smsg->message); -} - -const char *sbus_member(const struct sbusmsg *smsg) -{ - return dbus_message_get_member(smsg->message); -} - -/* - * 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 sbus_reply_error(struct sbusmsg *smsg, const char *error) -{ - int rc = -1; - DBusMessage *message; - - message = dbus_message_new_error(smsg->message, DBUS_ERROR_FAILED, - error); - if (message == NULL) - errno = ENOMEM; - else { - if (dbus_connection_send(smsg->connection, message, NULL)) - rc = 0; - dbus_message_unref(message); - } - free_sbusmsg(smsg); - return rc; -} - -/* - * 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 sbus_reply(struct sbusmsg *smsg, const char *reply) -{ - int rc = -1; - DBusMessage *message; - - message = dbus_message_new_method_return(smsg->message); - if (message == NULL) - return reply_out_of_memory(smsg); - - if (!dbus_message_append_args - (message, DBUS_TYPE_STRING, &reply, DBUS_TYPE_INVALID)) { - dbus_message_unref(message); - return reply_out_of_memory(smsg); - } - - if (dbus_connection_send(smsg->connection, message, NULL)) - rc = 0; - dbus_message_unref(message); - free_sbusmsg(smsg); - return rc; -} - -/****************** FEW LITTLE TESTS *****************************************/ - -#if defined(SERVER)||defined(CLIENT) -#include <stdio.h> -#include <unistd.h> -#include "utils-upoll.h" - -static int mwait(int timeout, void *closure) -{ - upoll_wait(timeout); - return 0; -} - -static const struct sbus_itf uitf = { - .wait = (void*)mwait, - .open = (void*)upoll_open, - .on_readable = (void*)upoll_on_readable, - .on_writable = (void*)upoll_on_writable, - .on_hangup = (void*)upoll_on_hangup, - .close = (void*)upoll_close -}; - -static const char name[] = "org.toto"; -static const char path[] = "/org/toto"; -static const char iface[] = "org.toto"; -static struct sbus *sbus; - -#ifdef SERVER -void ping(struct sbusmsg *smsg, const char *request, void *unused) -{ - printf("ping(%s) -> %s\n", request, request); - sbus_reply(smsg, request); -} - -void incr(struct sbusmsg *smsg, const char *request, void *unused) -{ - static int counter = 0; - char res[150]; - sprintf(res, "%d", ++counter); - printf("incr(%s) -> %s\n", request, res); - sbus_reply(smsg, res); - sbus_send_signal(sbus, name, path, iface, "incremented", res); -} - -int main() -{ - int s1, s2, s3; - sbus = sbus_session(&uitf, NULL); - s3 = !sbus_add_name(sbus, name); - s1 = !!sbus_add_service(sbus, name, path, iface, "ping", ping, NULL); - s2 = !!sbus_add_service(sbus, name, path, iface, "incr", incr, NULL); - printf("started %d %d %d\n", s1, s2, s3); - while (1) upoll_wait(-1); -} -#endif - -#ifdef CLIENT -void onresp(int status, const char *response, void *closure) -{ - printf("resp: %d, %s, %s\n", status, (const char *)closure, response); -} - -void signaled(const struct sbusmsg *req, const char *data, void *closure) -{ - printf("signaled with {%s}/%s\n", data, (const char*)closure); -} - -int main() -{ - int i = 10; - sbus = sbus_session(&uitf, NULL); - sbus_add_signal(sbus, name, path, iface, "incremented", signaled, "signal"); - while (i--) { - sbus_call(sbus, name, path, iface, "ping", "{'toto':[1,2,3,4,true,'toto']}", onresp, "ping"); - sbus_call(sbus, name, path, iface, "incr", "{'doit':'for-me'}", onresp, "incr"); - upoll_wait(1); - } - printf("[[[%s]]]\n", sbus_call_sync(sbus, name, path, iface, "ping", "formidable!")); - while (1) upoll_wait(-1); -} -#endif -#endif |