X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fat-spi2-atk.git;a=blobdiff_plain;f=droute%2Fdroute.c;h=0a0bfd6bfc34d45cdba5dac409ea68150cebaa97;hp=e4c1f91eb1c298fc181eb024b1672b0d5cd20487;hb=a9691925d9a5e2eb32009de2cc6bfa4b9f168945;hpb=613dc5600b5e84cd2108f9813fd1eb7cef4263e6 diff --git a/droute/droute.c b/droute/droute.c index e4c1f91..0a0bfd6 100644 --- a/droute/droute.c +++ b/droute/droute.c @@ -3,6 +3,7 @@ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) * * Copyright 2008 Novell, Inc. + * Copyright 2008 Codethink Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -22,313 +23,704 @@ #include #include +#include #include "droute.h" +#include "droute-pairhash.h" -static DRouteInterface * -find_iface (DRouteData * data, const char *name) +#define CHUNKS_DEFAULT (512) + +#define oom() g_error ("D-Bus out of memory, this message will fail anyway") + +#if defined DROUTE_DEBUG + #define _DROUTE_DEBUG(format, args...) g_print (format , ## args) +#else + #define _DROUTE_DEBUG(format, args...) +#endif + +struct _DRouteContext { - GSList *l; + GPtrArray *registered_paths; - for (l = data->interfaces; l; l = g_slist_next (l)) - { - DRouteInterface *iface = (DRouteInterface *) l->data; - if (iface && iface->name && !strcmp (iface->name, name)) - return iface; - } - return NULL; + gchar *introspect_string; +}; + +struct _DRoutePath +{ + DRouteContext *cnx; + gchar *path; + gboolean prefix; + GStringChunk *chunks; + GPtrArray *interfaces; + GPtrArray *introspection; + GHashTable *methods; + GHashTable *properties; + + DRouteIntrospectChildrenFunction introspect_children_cb; + void *introspect_children_data; + void *user_data; + DRouteGetDatumFunction get_datum; +}; + +/*---------------------------------------------------------------------------*/ + +typedef struct PropertyPair +{ + DRoutePropertyFunction get; + DRoutePropertyFunction set; +} PropertyPair; + +/*---------------------------------------------------------------------------*/ + +static DBusHandlerResult +handle_message (DBusConnection *bus, DBusMessage *message, void *user_data); + +static DBusMessage * +droute_object_does_not_exist_error (DBusMessage *message); + +/*---------------------------------------------------------------------------*/ + +static DRoutePath * +path_new (DRouteContext *cnx, + const char *path, + gboolean prefix, + void *user_data, + DRouteIntrospectChildrenFunction introspect_children_cb, + void *introspect_children_data, + DRouteGetDatumFunction get_datum) +{ + DRoutePath *new_path; + + new_path = g_new0 (DRoutePath, 1); + new_path->cnx = cnx; + new_path->path = g_strdup (path); + new_path->prefix = prefix; + new_path->chunks = g_string_chunk_new (CHUNKS_DEFAULT); + new_path->interfaces = g_ptr_array_new (); + new_path->introspection = g_ptr_array_new (); + + new_path->methods = g_hash_table_new_full ((GHashFunc)str_pair_hash, + str_pair_equal, + g_free, + NULL); + + new_path->properties = g_hash_table_new_full ((GHashFunc)str_pair_hash, + str_pair_equal, + g_free, + g_free); + + new_path->introspect_children_cb = introspect_children_cb; + new_path->introspect_children_data = introspect_children_data; + new_path->user_data = user_data; + new_path->get_datum = get_datum; + + return new_path; +} + +static void +path_free (DRoutePath *path, gpointer user_data) +{ + g_free (path->path); + g_string_chunk_free (path->chunks); + g_ptr_array_free (path->interfaces, TRUE); + g_free(g_ptr_array_free (path->introspection, FALSE)); + g_hash_table_destroy (path->methods); + g_hash_table_destroy (path->properties); +} + +static void * +path_get_datum (DRoutePath *path, const gchar *pathstr) +{ + if (path->get_datum != NULL) + return (path->get_datum) (pathstr, path->user_data); + else + return path->user_data; +} + +/*---------------------------------------------------------------------------*/ + +DRouteContext * +droute_new () +{ + DRouteContext *cnx; + + cnx = g_new0 (DRouteContext, 1); + cnx->registered_paths = g_ptr_array_new (); + + return cnx; +} + +void +droute_free (DRouteContext *cnx) +{ + g_ptr_array_foreach (cnx->registered_paths, (GFunc) path_free, NULL); + g_free (cnx); +} + +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ + +static DBusObjectPathVTable droute_vtable = +{ + NULL, + &handle_message, + NULL, NULL, NULL, NULL +}; + +DRoutePath * +droute_add_one (DRouteContext *cnx, + const char *path, + const void *data) +{ + DRoutePath *new_path; + + new_path = path_new (cnx, path, FALSE, (void *)data, NULL, NULL, NULL); + + g_ptr_array_add (cnx->registered_paths, new_path); + return new_path; +} + +DRoutePath * +droute_add_many (DRouteContext *cnx, + const char *path, + const void *data, + DRouteIntrospectChildrenFunction introspect_children_cb, + void *introspect_children_data, + const DRouteGetDatumFunction get_datum) +{ + DRoutePath *new_path; + + new_path = path_new (cnx, path, TRUE, (void *) data, + introspect_children_cb, introspect_children_data, + get_datum); + + g_ptr_array_add (cnx->registered_paths, new_path); + return new_path; +} + +/*---------------------------------------------------------------------------*/ + +void +droute_path_add_interface(DRoutePath *path, + const char *name, + const char *introspect, + const DRouteMethod *methods, + const DRouteProperty *properties) +{ + gchar *itf; + + g_return_if_fail (name != NULL); + + itf = g_string_chunk_insert (path->chunks, name); + g_ptr_array_add (path->interfaces, itf); + g_ptr_array_add (path->introspection, (gpointer) introspect); + + for (; methods != NULL && methods->name != NULL; methods++) + { + gchar *meth; + + meth = g_string_chunk_insert (path->chunks, methods->name); + g_hash_table_insert (path->methods, str_pair_new (itf, meth), methods->func); + } + + for (; properties != NULL && properties->name != NULL; properties++) + { + gchar *prop; + PropertyPair *pair; + + prop = g_string_chunk_insert (path->chunks, properties->name); + pair = g_new (PropertyPair, 1); + pair->get = properties->get; + pair->set = properties->set; + g_hash_table_insert (path->properties, str_pair_new (itf, prop), pair); + } +} + +/*---------------------------------------------------------------------------*/ + +/* The data structures don't support an efficient implementation of GetAll + * and I don't really care. + */ +static DBusMessage * +impl_prop_GetAll (DBusMessage *message, + DRoutePath *path, + const char *pathstr) +{ + DBusMessageIter iter, iter_dict, iter_dict_entry; + DBusMessage *reply; + DBusError error; + GHashTableIter prop_iter; + + StrPair *key; + PropertyPair *value; + gchar *iface; + + void *datum = path_get_datum (path, pathstr); + if (!datum) + return droute_object_does_not_exist_error (message); + + dbus_error_init (&error); + if (!dbus_message_get_args + (message, &error, DBUS_TYPE_STRING, &iface, DBUS_TYPE_INVALID)) + return dbus_message_new_error (message, DBUS_ERROR_FAILED, error.message); + + reply = dbus_message_new_method_return (message); + if (!reply) + oom (); + + dbus_message_iter_init_append (reply, &iter); + if (!dbus_message_iter_open_container + (&iter, DBUS_TYPE_ARRAY, "{sv}", &iter_dict)) + oom (); + + g_hash_table_iter_init (&prop_iter, path->properties); + while (g_hash_table_iter_next (&prop_iter, (gpointer*)&key, (gpointer*)&value)) + { + if (!g_strcmp0 (key->one, iface)) + { + if (!value->get) + continue; + if (!dbus_message_iter_open_container + (&iter_dict, DBUS_TYPE_DICT_ENTRY, NULL, &iter_dict_entry)) + oom (); + dbus_message_iter_append_basic (&iter_dict_entry, DBUS_TYPE_STRING, + &key->two); + (value->get) (&iter_dict_entry, datum); + if (!dbus_message_iter_close_container (&iter_dict, &iter_dict_entry)) + oom (); + } + } + + if (!dbus_message_iter_close_container (&iter, &iter_dict)) + oom (); + return reply; +} + +static DBusMessage * +impl_prop_GetSet (DBusMessage *message, + DRoutePath *path, + const char *pathstr, + gboolean get) +{ + DBusMessage *reply = NULL; + DBusError error; + + StrPair pair; + PropertyPair *prop_funcs = NULL; + + void *datum; + + dbus_error_init (&error); + if (!dbus_message_get_args (message, + &error, + DBUS_TYPE_STRING, + &(pair.one), + DBUS_TYPE_STRING, + &(pair.two), + DBUS_TYPE_INVALID)) + return dbus_message_new_error (message, DBUS_ERROR_FAILED, error.message); + + _DROUTE_DEBUG ("DRoute (handle prop): %s|%s on %s\n", pair.one, pair.two, pathstr); + + prop_funcs = (PropertyPair *) g_hash_table_lookup (path->properties, &pair); + if (!prop_funcs) +#ifdef DBUS_ERROR_UNKNOWN_PROPERTY + return dbus_message_new_error (message, DBUS_ERROR_UNKNOWN_PROPERTY, "Property unavailable"); +#else + return dbus_message_new_error (message, DBUS_ERROR_FAILED, "Property unavailable"); +#endif + + datum = path_get_datum (path, pathstr); + if (!datum) + return droute_object_does_not_exist_error (message); + + if (get && prop_funcs->get) + { + + DBusMessageIter iter; + + _DROUTE_DEBUG ("DRoute (handle prop Get): %s|%s on %s\n", pair.one, pair.two, pathstr); + + reply = dbus_message_new_method_return (message); + dbus_message_iter_init_append (reply, &iter); + if (!(prop_funcs->get) (&iter, datum)) + { + dbus_message_unref (reply); + reply = dbus_message_new_error (message, DBUS_ERROR_FAILED, "Get failed"); + } + } + else if (!get && prop_funcs->set) + { + DBusMessageIter iter; + + _DROUTE_DEBUG ("DRoute (handle prop Get): %s|%s on %s\n", pair.one, pair.two, pathstr); + + dbus_message_iter_init (message, &iter); + /* Skip the interface and property name */ + dbus_message_iter_next(&iter); + dbus_message_iter_next(&iter); + (prop_funcs->set) (&iter, datum); + + reply = dbus_message_new_method_return (message); + } +#ifdef DBUS_ERROR_PROPERTY_READ_ONLY + else if (!get) + { + reply = dbus_message_new_error (message, DBUS_ERROR_PROPERTY_READ_ONLY, "Property is read-only"); + } +#endif + else + { + reply = dbus_message_new_error (message, DBUS_ERROR_FAILED, "Getter or setter unavailable"); + } + + return reply; } static DBusHandlerResult -prop_get_all (DBusConnection * bus, DBusMessage * message, DRouteData * data) +handle_dbus (DBusConnection *bus, + DBusMessage *message, + const gchar *iface, + const gchar *member, + const gchar *pathstr) { - DRouteInterface *iface_def; - DRouteProperty *prop; - DBusError error; - const char *iface; - const char *path = dbus_message_get_path (message); + static int id = 1; + char *id_str = (char *) g_malloc(40); DBusMessage *reply; - DBusMessageIter iter, iter_dict, iter_dict_entry; - dbus_error_init (&error); - if (!dbus_message_get_args - (message, &error, DBUS_TYPE_STRING, &iface, DBUS_TYPE_INVALID)) + if (strcmp (iface, DBUS_INTERFACE_DBUS) != 0 || + strcmp (member, "Hello") != 0) { + g_free (id_str); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } - reply = dbus_message_new_method_return (message); - /* tbd: replace tbd with todo? */ - if (!reply) - goto oom; - dbus_message_iter_init_append (reply, &iter); - if (!dbus_message_iter_open_container - (&iter, DBUS_TYPE_ARRAY, "{sv}", &iter_dict)) - goto oom; - iface_def = find_iface (data, iface); - if (!iface_def) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - if (iface_def->properties) - for (prop = iface_def->properties; prop->name; prop++) + + /* TODO: Fix this hack (we don't handle wrap-around, for instance) */ + sprintf (id_str, ":1.%d", id++); + reply = dbus_message_new_method_return (message); + dbus_message_append_args (reply, DBUS_TYPE_STRING, &id_str, DBUS_TYPE_INVALID); + dbus_connection_send (bus, reply, NULL); + dbus_connection_flush (bus); + dbus_message_unref (reply); + g_free (id_str); + return DBUS_HANDLER_RESULT_HANDLED; +} + +static DBusHandlerResult +handle_properties (DBusConnection *bus, + DBusMessage *message, + DRoutePath *path, + const gchar *iface, + const gchar *member, + const gchar *pathstr) +{ + DBusMessage *reply = NULL; + DBusHandlerResult result = DBUS_HANDLER_RESULT_HANDLED; + + if (!g_strcmp0(member, "GetAll")) + reply = impl_prop_GetAll (message, path, pathstr); + else if (!g_strcmp0 (member, "Get")) + reply = impl_prop_GetSet (message, path, pathstr, TRUE); + else if (!g_strcmp0 (member, "Set")) + reply = impl_prop_GetSet (message, path, pathstr, FALSE); + else + result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + if (reply) { - if (!prop->get) - continue; - if (!dbus_message_iter_open_container - (&iter_dict, DBUS_TYPE_DICT_ENTRY, NULL, &iter_dict_entry)) - goto oom; - dbus_message_iter_append_basic (&iter_dict_entry, DBUS_TYPE_STRING, - &prop->name); - (*prop->get) (path, &iter_dict_entry, data->user_data); - if (!dbus_message_iter_close_container (&iter_dict, &iter_dict_entry)) - goto oom; + dbus_connection_send (bus, reply, NULL); + dbus_message_unref (reply); } - if (!dbus_message_iter_close_container (&iter, &iter_dict)) - goto oom; - dbus_connection_send (bus, reply, NULL); - dbus_message_unref (reply); - return DBUS_HANDLER_RESULT_HANDLED; -oom: - /* tbd: return a standard out-of-memory error */ - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + return result; } +/*---------------------------------------------------------------------------*/ + +static const char *introspection_header = +"\n"; + +static const char *introspection_node_element = +"\n"; + +static const char *introspection_footer = +""; + static DBusHandlerResult -prop (DBusConnection * bus, DBusMessage * message, DRouteData * data) +handle_introspection (DBusConnection *bus, + DBusMessage *message, + DRoutePath *path, + const gchar *iface, + const gchar *member, + const gchar *pathstr) { - const char *mode = dbus_message_get_member (message); - const char *iface, *member; - const char *path = dbus_message_get_path (message); - int set; - DBusMessage *reply; - DBusMessageIter iter; - DRouteInterface *iface_def; - DRouteProperty *prop = NULL; - - if (!strcmp (mode, "Set")) - set = 1; - else if (!strcmp (mode, "Get")) - set = 0; - else - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - reply = dbus_message_new_method_return (message); - dbus_message_iter_init (message, &iter); - dbus_message_iter_get_basic (&iter, &iface); - dbus_message_iter_next (&iter); - dbus_message_iter_get_basic (&iter, &member); - if (!set) - dbus_message_iter_init_append (reply, &iter); - iface_def = find_iface (data, iface); - if (!iface_def) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - if (iface_def->properties) - for (prop = iface_def->properties; - prop->name && strcmp (prop->name, member); prop++) - if (!prop || !prop->name) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - if (set) - { - if (!prop->set) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - (*prop->set) (path, &iter, data->user_data); - } - else - { - if (!prop->get) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - (*prop->get) (path, &iter, data->user_data); - } - dbus_connection_send (bus, reply, NULL); - dbus_message_unref (reply); - return DBUS_HANDLER_RESULT_HANDLED; + GString *output; + gchar *final; + gint i; + + DBusMessage *reply; + + _DROUTE_DEBUG ("DRoute (handle introspection): %s\n", pathstr); + + if (g_strcmp0 (member, "Introspect")) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + output = g_string_new(introspection_header); + + g_string_append_printf(output, introspection_node_element, pathstr); + + if (!path->get_datum || path_get_datum (path, pathstr)) + { + for (i=0; i < path->introspection->len; i++) + { + gchar *introspect = (gchar *) g_ptr_array_index (path->introspection, i); + g_string_append (output, introspect); + } + } + + if (path->introspect_children_cb) + { + gchar *children = (*path->introspect_children_cb) (pathstr, path->introspect_children_data); + if (children) + { + g_string_append (output, children); + g_free (children); + } + } + + g_string_append(output, introspection_footer); + final = g_string_free(output, FALSE); + + reply = dbus_message_new_method_return (message); + if (!reply) + oom (); + dbus_message_append_args(reply, DBUS_TYPE_STRING, &final, + DBUS_TYPE_INVALID); + dbus_connection_send (bus, reply, NULL); + + dbus_message_unref (reply); + g_free(final); + return DBUS_HANDLER_RESULT_HANDLED; } -DBusHandlerResult -droute_message (DBusConnection * bus, DBusMessage * message, void *user_data) +/*---------------------------------------------------------------------------*/ + +static DBusHandlerResult +handle_other (DBusConnection *bus, + DBusMessage *message, + DRoutePath *path, + const gchar *iface, + const gchar *member, + const gchar *pathstr) { - DRouteData *data = (DRouteData *) user_data; - DRouteInterface *iface_def; - DRouteMethod *method; - const char *iface = dbus_message_get_interface (message); - const char *member = dbus_message_get_member (message); - int type; - DBusError error; - DBusMessage *reply; + gint result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - dbus_error_init (&error); - if (!member) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - if (iface && !strcmp (iface, "org.freedesktop.DBus.Properties")) - { - if (!strcmp (member, "GetAll")) - return prop_get_all (bus, message, data); - return prop (bus, message, data); - } - if (iface) - { - iface_def = find_iface (data, iface); - if (!iface_def) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - if (iface_def->methods) - for (method = iface_def->methods; method->func; method++) - { - if (!strcmp (method->name, member)) - { - reply = - (*method->func) (bus, message, - (method->wants_droute_data ? data : data-> - user_data)); - if (reply) - { - dbus_connection_send (bus, reply, NULL); - dbus_message_unref (reply); - } - return DBUS_HANDLER_RESULT_HANDLED; - } - } - } - else - { - GSList *l; - if (type == DBUS_MESSAGE_TYPE_SIGNAL) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - for (l = data->interfaces; l; l = g_slist_next (l)) - { - iface_def = (DRouteInterface *) l->data; - if (iface_def->methods) - for (method = iface_def->methods; method->func; method++) - { - if (!strcmp (method->name, member)) - { - reply = (*method->func) (bus, message, data->user_data); - if (reply) - { - dbus_connection_send (bus, reply, NULL); - dbus_message_unref (reply); - } - return DBUS_HANDLER_RESULT_HANDLED; - } - } - } - } - return DBUS_HANDLER_RESULT_HANDLED; + StrPair pair; + DRouteFunction func; + DBusMessage *reply = NULL; + + void *datum; + + pair.one = iface; + pair.two = member; + + _DROUTE_DEBUG ("DRoute (handle other): %s|%s on %s\n", member, iface, pathstr); + + func = (DRouteFunction) g_hash_table_lookup (path->methods, &pair); + if (func != NULL) + { + datum = path_get_datum (path, pathstr); + if (!datum) + reply = droute_object_does_not_exist_error (message); + else + reply = (func) (bus, message, datum); + + /* All D-Bus method calls must have a reply. + * If one is not provided presume that the caller has already + * sent one. + */ + if (reply) + { + dbus_connection_send (bus, reply, NULL); + dbus_message_unref (reply); + } + result = DBUS_HANDLER_RESULT_HANDLED; + } + + _DROUTE_DEBUG ("DRoute (handle other) (reply): type %d\n", + dbus_message_get_type(reply)); + return result; } -dbus_bool_t -droute_return_v_int32 (DBusMessageIter * iter, dbus_int32_t val) +/*---------------------------------------------------------------------------*/ + +static DBusHandlerResult +handle_message (DBusConnection *bus, DBusMessage *message, void *user_data) { - DBusMessageIter sub; + DRoutePath *path = (DRoutePath *) user_data; + const gchar *iface = dbus_message_get_interface (message); + const gchar *member = dbus_message_get_member (message); + const gint type = dbus_message_get_type (message); + const gchar *pathstr = dbus_message_get_path (message); - if (!dbus_message_iter_open_container - (iter, DBUS_TYPE_VARIANT, DBUS_TYPE_INT32_AS_STRING, &sub)) - { - return FALSE; - } - dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &val); - dbus_message_iter_close_container (iter, &sub); - return TRUE; + DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + _DROUTE_DEBUG ("DRoute (handle message): %s|%s of type %d on %s\n", member, iface, type, pathstr); + + /* Check for basic reasons not to handle */ + if (type != DBUS_MESSAGE_TYPE_METHOD_CALL || + member == NULL || + iface == NULL) + return result; + + if (!strcmp (pathstr, DBUS_PATH_DBUS)) + result = handle_dbus (bus, message, iface, member, pathstr); + else if (!strcmp (iface, "org.freedesktop.DBus.Properties")) + result = handle_properties (bus, message, path, iface, member, pathstr); + else if (!strcmp (iface, "org.freedesktop.DBus.Introspectable")) + result = handle_introspection (bus, message, path, iface, member, pathstr); + else + result = handle_other (bus, message, path, iface, member, pathstr); +#if 0 + if (result == DBUS_HANDLER_RESULT_NOT_YET_HANDLED) + g_print ("DRoute | Unhandled message: %s|%s of type %d on %s\n", member, iface, type, pathstr); +#endif + + return result; } -dbus_bool_t -droute_return_v_double (DBusMessageIter * iter, double val) +/*---------------------------------------------------------------------------*/ + +static DBusMessage * +droute_object_does_not_exist_error (DBusMessage *message) { - DBusMessageIter sub; + DBusMessage *reply; + gchar *errmsg; - if (!dbus_message_iter_open_container - (iter, DBUS_TYPE_VARIANT, DBUS_TYPE_DOUBLE_AS_STRING, &sub)) - { - return FALSE; - } - dbus_message_iter_append_basic (&sub, DBUS_TYPE_DOUBLE, &val); - dbus_message_iter_close_container (iter, &sub); - return TRUE; + errmsg= g_strdup_printf ( + "Method \"%s\" with signature \"%s\" on interface \"%s\" could not be processed as object %s does not exist\n", + dbus_message_get_member (message), + dbus_message_get_signature (message), + dbus_message_get_interface (message), + dbus_message_get_path (message)); +#ifdef DBUS_ERROR_UNKNOWN_OBJECT + reply = dbus_message_new_error (message, + DBUS_ERROR_UNKNOWN_OBJECT, + errmsg); +#else + reply = dbus_message_new_error (message, + DBUS_ERROR_FAILED, + errmsg); +#endif + g_free (errmsg); + return reply; } -/* Return a string in a variant - * will return an empty string if passed a NULL value */ -dbus_bool_t -droute_return_v_string (DBusMessageIter * iter, const char *val) +/*---------------------------------------------------------------------------*/ + +DBusMessage * +droute_not_yet_handled_error (DBusMessage *message) { - DBusMessageIter sub; + DBusMessage *reply; + gchar *errmsg; - if (!val) - val = ""; - if (!dbus_message_iter_open_container - (iter, DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &sub)) - { - return FALSE; - } - dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING, &val); - dbus_message_iter_close_container (iter, &sub); - return TRUE; + errmsg= g_strdup_printf ( + "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n", + dbus_message_get_member (message), + dbus_message_get_signature (message), + dbus_message_get_interface (message)); + reply = dbus_message_new_error (message, + DBUS_ERROR_UNKNOWN_METHOD, + errmsg); + g_free (errmsg); + return reply; } -dbus_int32_t -droute_get_v_int32 (DBusMessageIter * iter) +DBusMessage * +droute_out_of_memory_error (DBusMessage *message) { - DBusMessageIter sub; - dbus_int32_t rv; + DBusMessage *reply; + gchar *errmsg; - // TODO- ensure we have the correct type - dbus_message_iter_recurse (iter, &sub); - dbus_message_iter_get_basic (&sub, &rv); - return rv; + errmsg= g_strdup_printf ( + "Method \"%s\" with signature \"%s\" on interface \"%s\" could not be processed due to lack of memory\n", + dbus_message_get_member (message), + dbus_message_get_signature (message), + dbus_message_get_interface (message)); + reply = dbus_message_new_error (message, + DBUS_ERROR_NO_MEMORY, + errmsg); + g_free (errmsg); + return reply; } -const char * -droute_get_v_string (DBusMessageIter * iter) +DBusMessage * +droute_invalid_arguments_error (DBusMessage *message) { - DBusMessageIter sub; - char *rv; + DBusMessage *reply; + gchar *errmsg; - // TODO- ensure we have the correct type - dbus_message_iter_recurse (iter, &sub); - dbus_message_iter_get_basic (&sub, &rv); - return rv; + errmsg= g_strdup_printf ( + "Method \"%s\" with signature \"%s\" on interface \"%s\" was supplied with invalid arguments\n", + dbus_message_get_member (message), + dbus_message_get_signature (message), + dbus_message_get_interface (message)); + reply = dbus_message_new_error (message, + DBUS_ERROR_INVALID_ARGS, + errmsg); + g_free (errmsg); + return reply; } -dbus_bool_t -droute_return_v_object (DBusMessageIter * iter, const char *path) +void +droute_path_register (DRoutePath *path, DBusConnection *bus) { - DBusMessageIter sub; + if (path->prefix) + dbus_connection_register_fallback (bus, path->path, &droute_vtable, path); + else + dbus_connection_register_object_path (bus, path->path, + &droute_vtable, path); +} - if (!dbus_message_iter_open_container - (iter, DBUS_TYPE_VARIANT, DBUS_TYPE_OBJECT_PATH_AS_STRING, &sub)) - { - return FALSE; - } - dbus_message_iter_append_basic (&sub, DBUS_TYPE_OBJECT_PATH, &path); - dbus_message_iter_close_container (iter, &sub); - return TRUE; +void +droute_path_unregister (DRoutePath *path, DBusConnection *bus) +{ + dbus_connection_unregister_object_path (bus, path->path); } -dbus_bool_t -droute_add_interface (DRouteData * data, const char *name, - DRouteMethod * methods, DRouteProperty * properties, - DRouteGetDatumFunction get_datum, - DRouteFreeDatumFunction free_datum) +void +droute_context_register (DRouteContext *cnx, DBusConnection *bus) { - DRouteInterface *iface = - (DRouteInterface *) malloc (sizeof (DRouteInterface)); - GSList *new_list; - - if (!iface) - return FALSE; - iface->name = strdup (name); - if (!iface->name) - { - free (iface); - return FALSE; - } - iface->methods = methods; - iface->properties = properties; - iface->get_datum = get_datum; - iface->free_datum = free_datum; - new_list = g_slist_append (data->interfaces, iface); - if (!new_list) - { - free (iface->name); - free (iface); - return FALSE; - } - data->interfaces = new_list; - return TRUE; + g_ptr_array_foreach (cnx->registered_paths, (GFunc) droute_path_register, + bus); +} + +void +droute_context_unregister (DRouteContext *cnx, DBusConnection *bus) +{ + g_ptr_array_foreach (cnx->registered_paths, (GFunc) droute_path_unregister, + bus); +} + +void +droute_context_deregister (DRouteContext *cnx, DBusConnection *bus) +{ + g_ptr_array_foreach (cnx->registered_paths, (GFunc) droute_path_unregister, + bus); +} + +void +droute_intercept_dbus (DBusConnection *bus) +{ + dbus_connection_register_object_path (bus, DBUS_PATH_DBUS, + &droute_vtable, NULL); +} + +void +droute_unintercept_dbus (DBusConnection *bus) +{ + dbus_connection_unregister_object_path (bus, DBUS_PATH_DBUS); } + +/*END------------------------------------------------------------------------*/