summaryrefslogtreecommitdiffstats
path: root/plugins/afm-main-plugin/utils-sbus.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/afm-main-plugin/utils-sbus.c')
-rw-r--r--plugins/afm-main-plugin/utils-sbus.c1037
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