-/*
- * 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, void *data)
-{
- struct respsync *s = data;
- s->value = status ? NULL : strdup(value ? value : "");
- s->replied = 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 DBUS MESSAGE HANDLING *****************/
-
-/*
- * Handles incomming responses 'message' on 'jbus'. 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 jbus *jbus,
- DBusMessage * message,
- int iserror)
-{
- int status;
- const char *str;
- struct jrespw *jrw, **prv;
- struct json_object *reply;
- dbus_uint32_t serial;
-
- /* search for the waiter */
- serial = dbus_message_get_reply_serial(message);
- prv = &jbus->waiters;
- while ((jrw = *prv) != NULL && jrw->serial != serial)
- prv = &jrw->next;
- if (jrw == NULL)
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
- *prv = jrw->next;
-
- /* 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;
- reply = NULL;
- }
-
- /* treat it */
- if (jrw->onresp_s)
- jrw->onresp_s(iserror ? -1 : status, str, jrw->data);
- else {
- status = jparse(jbus, str, &reply) - 1;
- jrw->onresp_j(iserror ? -1 : status, reply, jrw->data);
- json_object_put(reply);
- }
-
- free(jrw);
- return DBUS_HANDLER_RESULT_HANDLED;
-}
-
-/*
- * Handles incomming on 'jbus' 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 jbus *jbus,
- DBusMessage * message)
-{
- struct jservice *srv;
- struct jreq *jreq;
- const char *str;
- const char *method;
- struct json_object *query;
-
- /* search for the service */
- if (!matchitf(jbus, message))
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
- method = dbus_message_get_member(message);
- if (method == NULL)
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
- srv = jbus->services;
- while (srv != NULL && strcmp(method, srv->method))
- srv = srv->next;
- if (srv == NULL)
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
- /* creates and init the jreq structure */
- jreq = malloc(sizeof *jreq);
- if (jreq == NULL)
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
- jreq->request = dbus_message_ref(message);
- jreq->connection = dbus_connection_ref(jbus->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;
-
- /* send the message to the callback */
- if (srv->oncall_s) {
- /* handling strings only */
- srv->oncall_s(jreq, str, srv->data);
- } else {
- /* handling json only */
- if (!jparse(jbus, str, &query))
- goto invalid_request;
- srv->oncall_j(jreq, query, srv->data);
- json_object_put(query);
- }
- return DBUS_HANDLER_RESULT_HANDLED;
-
-invalid_request:
- jbus_reply_error_s(jreq, invalid_request_string);
- return DBUS_HANDLER_RESULT_HANDLED;
-}
-
-/*
- * Handles incomming on 'jbus' 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 jbus *jbus,
- DBusMessage * message)
-{
- struct jsignal *sig;
- const char *str;
- const char *name;
- struct json_object *obj;
-
- /* search for the signal name */
- if (!matchitf(jbus, message))
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
- name = dbus_message_get_member(message);
- if (name == NULL)
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
- sig = jbus->signals;
- while (sig != NULL && strcmp(name, sig->name))
- sig = sig->next;
- if (sig == NULL)
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
- /* retrieve the string value */
- if (dbus_message_get_args
- (message, NULL, DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID)) {
- if (sig->onsignal_s) {
- /* handling strings only */
- sig->onsignal_s(str, sig->data);
- } else {
- /* handling json only (if valid) */
- if (jparse(jbus, str, &obj)) {
- sig->onsignal_j(obj, sig->data);
- json_object_put(obj);
- }
- }
- }
- return DBUS_HANDLER_RESULT_HANDLED;
-}
-
-/*
- * 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,
- void *data)
-{
- struct jbus *jbus = data;
- switch (dbus_message_get_type(message)) {
- case DBUS_MESSAGE_TYPE_METHOD_CALL:
- return incoming_call(jbus, message);
- case DBUS_MESSAGE_TYPE_METHOD_RETURN:
- return incoming_resp(jbus, message, 0);
- case DBUS_MESSAGE_TYPE_ERROR:
- return incoming_resp(jbus, message, 1);
- case DBUS_MESSAGE_TYPE_SIGNAL:
- return incoming_signal(jbus, message);
- }
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-}
-
-/*********************** STATIC DBUS WATCH/POLLING INTERFACE **********/
-
-/*
- * Set the watched flags of 'jbus' following what DBUS expects by 'watch'
- */
-static void watchset(DBusWatch * watch, struct jbus *jbus)
-{
- unsigned int flags;
- short wf;
-
- flags = dbus_watch_get_flags(watch);
- wf = jbus->watchflags;
- if (dbus_watch_get_enabled(watch)) {
- if (flags & DBUS_WATCH_READABLE)
- wf |= POLLIN;
- if (flags & DBUS_WATCH_WRITABLE)
- wf |= POLLOUT;
- } else {
- if (flags & DBUS_WATCH_READABLE)
- wf &= ~POLLIN;
- if (flags & DBUS_WATCH_WRITABLE)
- wf &= ~POLLOUT;
- }
- jbus->watchflags = wf;
-}
-
-/*
- * DBUS Callback for removing a 'watch'.
- * See function 'dbus_connection_set_watch_functions'
- */
-static void watchdel(DBusWatch * watch, void *data)
-{
- struct jbus *jbus = data;
-
- assert(jbus->watchnr > 0);
- assert(jbus->watchfd == dbus_watch_get_unix_fd(watch));
- jbus->watchnr--;
-}
-
-/*
- * DBUS Callback for changing a 'watch'.
- * See function 'dbus_connection_set_watch_functions'
- */
-static void watchtoggle(DBusWatch * watch, void *data)
-{
- struct jbus *jbus = data;
-
- assert(jbus->watchnr > 0);
- assert(jbus->watchfd == dbus_watch_get_unix_fd(watch));
- watchset(watch, jbus);
-}
-
-/*
- * DBUS Callback for adding a 'watch'.
- * See function 'dbus_connection_set_watch_functions'
- */
-static dbus_bool_t watchadd(DBusWatch * watch, void *data)
-{
- struct jbus *jbus = data;
- if (jbus->watchnr == 0) {
- jbus->watchfd = dbus_watch_get_unix_fd(watch);
- jbus->watchflags = 0;
- } else if (jbus->watchfd != dbus_watch_get_unix_fd(watch))
- return FALSE;
- jbus->watchnr++;
- watchset(watch, jbus);
- return TRUE;
-}
-