diff options
author | Søren Sandmann Pedersen <sandmann@daimi.au.dk> | 2009-04-19 21:16:03 -0400 |
---|---|---|
committer | Søren Sandmann Pedersen <sandmann@daimi.au.dk> | 2009-04-19 21:16:03 -0400 |
commit | 9da7c4a39b96be96fb5c0c34ef305c81151df898 (patch) | |
tree | 6356d6d8a42d8e3dc26e1ad7b1b09c43a3a4e2f7 | |
parent | a7e801c5ab9e6257011007a4ac08cd604843dd96 (diff) |
Move lowlevel dbus stuff to dbus-int.c
-rw-r--r-- | dbus-int.c | 174 | ||||
-rw-r--r-- | dbus.c | 445 | ||||
-rw-r--r-- | libnul-private.h | 15 |
3 files changed, 223 insertions, 411 deletions
@@ -10,6 +10,7 @@ typedef struct object_info_t object_info_t; struct object_info_t { char * name; + connection_t * connection; message_func_t func; gpointer data; }; @@ -19,6 +20,8 @@ struct connection_t DBusConnection *dconnection; object_info_t **objects; + + char ** names; }; static void @@ -302,6 +305,7 @@ ensure_connection (connection_t **connection, conn = g_new0 (connection_t, 1); conn->dconnection = dconn; conn->objects = nul_array_new (object_info_t *); + conn->names = nul_array_new (char *); *connection = conn; } @@ -337,22 +341,22 @@ connection_new_system (void) } static void -unregister_connection (DBusConnection *connection, - gpointer data) +dbus_int_unregister_connection (DBusConnection *connection, + gpointer data) { /* nothing */ } static DBusHandlerResult -message_function (DBusConnection *connection, - DBusMessage *message, - gpointer data) +dbus_int_message_function (DBusConnection *connection, + DBusMessage *message, + gpointer data) { object_info_t *info = data; /* Parse the message into something sensible here */ - if (info->func ((void *)message, info->data)) + if (info->func (info->connection, message, info->data)) return DBUS_HANDLER_RESULT_HANDLED; else return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; @@ -360,8 +364,8 @@ message_function (DBusConnection *connection, static const DBusObjectPathVTable vtable = { - unregister_connection, - message_function, + dbus_int_unregister_connection, + dbus_int_message_function, NULL, }; @@ -372,6 +376,7 @@ connection_register_object (connection_t *connection, nul_ptr_t data) { object_info_t *info = g_new0 (object_info_t, 1); + info->connection = connection; info->name = g_strdup (object_name); info->func = func; info->data = data; @@ -379,7 +384,7 @@ connection_register_object (connection_t *connection, connection->objects = nul_array_append (connection->objects, info); dbus_connection_register_object_path ( - connection->dconnection, object_name, &vtable, data); + connection->dconnection, object_name, &vtable, info); } void @@ -404,3 +409,154 @@ connection_unregister_object (connection_t *connection, } } } + +static gboolean +owns_name (connection_t *connection, + const char *name) +{ + char **n; + + for (n = connection->names; *n; n++) + { + if (strcmp (*n, name) == 0) + return TRUE; + } + + return FALSE; +} + +void +connection_release_name (connection_t *connection, + const char * name) +{ + if (!owns_name (connection, name)) + return; + + /* FIXME: errors? */ + dbus_bus_release_name (connection->dconnection, name, NULL); +} + +gboolean +connection_request_name (connection_t *connection, + const char *name) +{ + int r; + gboolean owner; + + /* Possible flags: + * + * DBUS_NAME_FLAG_ALLOW_REPLACEMENT + * DBUS_NAME_FLAG_REPLACE_EXISTING + * DBUS_FLAG_DO_NOT_QUEUE + */ + + if (owns_name (connection, name)) + return TRUE; /* Should we g_critical here? */ + + r = dbus_bus_request_name (connection->dconnection, + name, DBUS_NAME_FLAG_DO_NOT_QUEUE, NULL); + + owner = FALSE; + + /* FIXME: errors */ + if (r == -1) + { + return FALSE; + } + else + { + switch (r) + { + case DBUS_REQUEST_NAME_REPLY_IN_QUEUE: + g_warning ("this should not happen according to dbus docs"); + break; + + case DBUS_REQUEST_NAME_REPLY_EXISTS: + break; + + case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER: + g_warning ("this should not happen"); + owner = TRUE; + break; + + case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER: + owner = TRUE; + break; + } + } + + if (owner) + { + connection->names = nul_array_append ( + connection->names, g_strdup (name)); + } + + return owner; +} + +typedef struct reply_info +{ + message_func_t func; + gpointer data; + connection_t *connection; +} reply_info_t; + +static void +dbus_int_handle_reply (DBusPendingCall *pending, + gpointer data) +{ + reply_info_t *info = data; + DBusMessage *reply; + + if (!info->func) + return; + + reply = dbus_pending_call_steal_reply (pending); + + if (!reply) + { + /* FIXME: can this happen? */ + + return; + } + + info->func (info->connection, reply, info->data); +} + +gboolean +connection_send_with_reply (connection_t *connection, + DBusMessage *message, + message_func_t func, + gpointer data) +{ + reply_info_t *info; + DBusPendingCall *pending; + + dbus_connection_send_with_reply ( + connection->dconnection, message, &pending, -1); + + if (!pending) + { + /* FIXME: we should do something, not sure what */ + return FALSE; + } + else + { + info = g_new0 (reply_info_t, 1); + + info->func = func; + info->data = data; + + dbus_pending_call_set_notify ( + pending, dbus_int_handle_reply, info, g_free); + + return TRUE; + } +} + +void +connection_send (connection_t *connection, + DBusMessage *message) +{ + connection_send_with_reply (connection, message, NULL, NULL); +} @@ -21,6 +21,7 @@ #include <dbus/dbus.h> #include <string.h> #include "libnul.h" +#include "libnul-private.h" #define INTROSPECT_INTERFACE "org.freedesktop.DBus.Introspectable" #define INTROSPECT_METHOD "Introspect" @@ -29,7 +30,7 @@ struct nul_dbus_service_t { char *name; nul_dbus_object_t **objects; - DBusConnection *connection; + connection_t *connection; gboolean running; DBusBusType type; }; @@ -85,218 +86,6 @@ struct nul_dbus_type_t Primitive type; }; -static void -process_watch (DBusWatch *watch, int flags) -{ - dbus_watch_handle (watch, flags); -} - -static void -on_hangup (gpointer data) -{ - DBusWatch *watch = data; - - process_watch (watch, DBUS_WATCH_HANGUP); -} - -static void -on_error (gpointer data) -{ - DBusWatch *watch = data; - - process_watch (watch, DBUS_WATCH_ERROR); -} - -static void -on_read (gpointer data) -{ - GList *list = data; - - for (list = data; list != NULL; list = list->next) - { - DBusWatch *watch = list->data; - - if (dbus_watch_get_enabled (watch) && - (dbus_watch_get_flags (watch) & DBUS_WATCH_READABLE)) - { - process_watch (watch, DBUS_WATCH_READABLE); - } - } -} - -static void -on_write (gpointer data) -{ - GList *list = data; - - for (list = data; list != NULL; list = list->next) - { - DBusWatch *watch = list->data; - - if (dbus_watch_get_enabled (watch) && - (dbus_watch_get_flags (watch) & DBUS_WATCH_WRITABLE)) - { - process_watch (watch, DBUS_WATCH_WRITABLE); - } - } -} - -static void -update_fd (int fd) -{ - int enabled, flags; - GList *watches, *list; - - watches = nul_fd_get_data (fd); - - enabled = FALSE; - flags = 0; - - for (list = watches; list != NULL; list = list->next) - { - DBusWatch *watch = list->data; - - if (dbus_watch_get_enabled (watch)) - { - enabled = TRUE; - flags |= dbus_watch_get_flags (watch); - } - } - - if (enabled) - { - nul_fd_set_error_callback (fd, on_hangup); - nul_fd_set_hangup_callback (fd, on_error); - - if (flags & DBUS_WATCH_READABLE) - nul_fd_set_read_callback (fd, on_read); - else - nul_fd_set_read_callback (fd, NULL); - - if (flags & DBUS_WATCH_WRITABLE) - nul_fd_set_write_callback (fd, on_write); - else - nul_fd_set_write_callback (fd, NULL); - } - else - { - nul_fd_set_error_callback (fd, NULL); - nul_fd_set_hangup_callback (fd, NULL); - nul_fd_set_read_callback (fd, NULL); - nul_fd_set_write_callback (fd, NULL); - } -} - -static dbus_bool_t -add_watch (DBusWatch *watch, void *data) -{ - DBusConnection *connection = data; - int fd = dbus_watch_get_unix_fd (watch); - - dbus_watch_set_data (watch, connection, NULL); - - /* DBus apparently will create multiple watches for - * the same fd. - */ - if (nul_fd_is_watched (fd)) - { - GList *watches = nul_fd_get_data (fd); - - watches = g_list_prepend (watches, watch); - - nul_fd_set_data (fd, watches); - } - else - { - nul_fd_add_watch (fd, g_list_prepend (NULL, watch)); - } - - update_fd (fd); - - return TRUE; -} - -static void -remove_watch (DBusWatch *watch, void *data) -{ - int fd = dbus_watch_get_unix_fd (watch); - GList *watches = nul_fd_get_data (fd); - - watches = g_list_remove (watches, watch); - - if (!watches) - { - nul_fd_remove_watch (fd); - } - else - { - nul_fd_set_data (fd, watches); - update_fd (fd); - } -} - -static void -toggle_watch (DBusWatch *watch, void *data) -{ - update_fd (dbus_watch_get_unix_fd (watch)); -} - -static gboolean -on_timeout (gpointer data) -{ - DBusTimeout *timeout = data; - - dbus_timeout_handle (timeout); - - return TRUE; -} - -static dbus_bool_t -add_timeout (DBusTimeout *timeout, void *data) -{ - dbus_timeout_set_data (timeout, GINT_TO_POINTER (0), NULL); - - if (dbus_timeout_get_enabled (timeout)) - { - int id; - - id = g_timeout_add (dbus_timeout_get_interval (timeout), - on_timeout, timeout); - - dbus_timeout_set_data (timeout, GINT_TO_POINTER (id), NULL); - } - - return TRUE; -} - -static void -remove_timeout (DBusTimeout *timeout, void *data) -{ - int id = GPOINTER_TO_INT (dbus_timeout_get_data (timeout)); - - if (id) - { - g_source_remove (id); - - dbus_timeout_set_data (timeout, GINT_TO_POINTER (0), NULL); - } -} - -static void -toggle_timeout (DBusTimeout *timeout, void *data) -{ - remove_timeout (timeout, NULL); - - add_timeout (timeout, NULL); -} - -static void -unregister_connection (DBusConnection *connection, - gpointer data) -{ - /* nothing */ -} - typedef void (* nul_free_func_t) (nul_ptr_t p); static nul_ptr_t *free_us; @@ -548,7 +337,7 @@ encode_message (DBusMessage *message, } static DBusHandlerResult -invoke (DBusConnection *connection, +invoke (connection_t *connection, nul_dbus_object_t *object, nul_dbus_member_t *member, DBusMessage *message) @@ -578,7 +367,7 @@ invoke (DBusConnection *connection, error_reply = dbus_message_new_error ( message, DBUS_ERROR_FAILED, "FIXME: generate a real error"); - dbus_connection_send (connection, error_reply, NULL); + connection_send (connection, error_reply); result = DBUS_HANDLER_RESULT_HANDLED; goto out; @@ -609,7 +398,7 @@ invoke (DBusConnection *connection, (nul_dbus_parameter_t **)&(member->parameters[member->n_inputs]), &(args[member->n_inputs + 1])); - dbus_connection_send (connection, reply, NULL); + connection_send (connection, reply); dbus_message_unref (reply); result = DBUS_HANDLER_RESULT_HANDLED; @@ -625,8 +414,8 @@ out: return result; } -static DBusHandlerResult -message_function (DBusConnection *connection, +static gboolean +message_function (connection_t *connection, DBusMessage *message, gpointer data) { @@ -649,9 +438,9 @@ message_function (DBusConnection *connection, DBUS_TYPE_STRING, &xml, DBUS_TYPE_INVALID); - dbus_connection_send (connection, reply, NULL); + connection_send (connection, reply); - return DBUS_HANDLER_RESULT_HANDLED; + return TRUE; } /* Normal method */ @@ -675,16 +464,9 @@ message_function (DBusConnection *connection, g_print ("got unknown message\n"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + return FALSE; } -static const DBusObjectPathVTable vtable = -{ - unregister_connection, - message_function, - NULL, -}; - static nul_ptr_t * make_ptr_array (gpointer first, va_list parameters) { @@ -707,97 +489,9 @@ make_ptr_array (gpointer first, va_list parameters) return array; } -static dbus_int32_t idle_id_slot = -1; - -static int -get_idle_id (DBusConnection *connection) -{ - if (idle_id_slot == -1) - dbus_connection_allocate_data_slot (&idle_id_slot); - - return (int)dbus_connection_get_data (connection, idle_id_slot); -} - -static void -set_idle_id (DBusConnection *connection, int id) -{ - if (idle_id_slot == -1) - dbus_connection_allocate_data_slot (&idle_id_slot); - - dbus_connection_set_data (connection, idle_id_slot, (void *)id, NULL); -} - -static gboolean -do_dispatch (gpointer data) -{ - DBusConnection *connection = data; - - while (dbus_connection_dispatch (connection) == DBUS_DISPATCH_DATA_REMAINS) - ; - - set_idle_id (connection, 0); - - return FALSE; -} - -static void -on_dispatch_status_changed (DBusConnection *connection, - DBusDispatchStatus new_status, - void *data) -{ - if (!get_idle_id (connection)) - set_idle_id (connection, g_idle_add (do_dispatch, connection)); -} - -static DBusConnection * -ensure_connection (DBusConnection **connection, - DBusBusType type, - DBusError *err) -{ - if (!*connection) - { - *connection = dbus_bus_get (type, err); - - if (*connection) - { - dbus_connection_set_dispatch_status_function ( - *connection, - on_dispatch_status_changed, *connection, NULL); - - dbus_connection_set_watch_functions ( - *connection, - add_watch, remove_watch, toggle_watch, - *connection, NULL); - - dbus_connection_set_timeout_functions ( - *connection, - add_timeout, remove_timeout, toggle_timeout, - *connection, NULL); - } - - do_dispatch (*connection); - } - - return *connection; -} - -static DBusConnection * -get_connection (DBusBusType type, DBusError *err) -{ - static DBusConnection *session_bus; - static DBusConnection *system_bus; - - if (type == DBUS_BUS_SESSION) - return ensure_connection (&session_bus, DBUS_BUS_SESSION, err); - else if (type == DBUS_BUS_SYSTEM) - return ensure_connection (&system_bus, DBUS_BUS_SYSTEM, err); - else - return NULL; -} - static nul_dbus_service_t * make_service (const char *name, - DBusBusType type, + connection_t *connection, nul_dbus_object_t *object1, va_list args) { @@ -807,9 +501,7 @@ make_service (const char *name, service->objects = (nul_dbus_object_t **)make_ptr_array (object1, args); - service->type = type; - - service->connection = get_connection (type, NULL); + service->connection = connection; if (!service->connection) { @@ -830,7 +522,7 @@ nul_dbus_session_service (const char *name, va_start (args, object1); - service = make_service (name, DBUS_BUS_SESSION, object1, args); + service = make_service (name, connection_new_session(), object1, args); va_end (args); @@ -840,62 +532,29 @@ nul_dbus_session_service (const char *name, gboolean nul_dbus_service_start (nul_dbus_service_t *service) { - DBusError err = DBUS_ERROR_INIT; int i; - int result; if (service->running) return FALSE; - /* Possible flags: - * - * DBUS_NAME_FLAG_ALLOW_REPLACEMENT - * DBUS_NAME_FLAG_REPLACE_EXISTING - * DBUS_FLAG_DO_NOT_QUEUE - */ - result = dbus_bus_request_name (service->connection, - service->name, - DBUS_NAME_FLAG_DO_NOT_QUEUE, - &err); - - if (result == -1) - { - /* FIXME: handle error */ - return FALSE; - } - - switch (result) + if (connection_request_name (service->connection, + service->name)) { - case DBUS_REQUEST_NAME_REPLY_IN_QUEUE: - g_assert_not_reached(); - break; - - case DBUS_REQUEST_NAME_REPLY_EXISTS: - g_print ("Couldn't get name\n"); - return FALSE; - break; - - case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER: - g_print ("We own this already (?)\n"); - return FALSE; - break; - - case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER: - break; - } + /* Register objects */ + for (i = 0; service->objects[i] != NULL; ++i) + { + nul_dbus_object_t *object = service->objects[i]; + + connection_register_object ( + service->connection, object->name, message_function, object); + } - /* Register objects */ - for (i = 0; service->objects[i] != NULL; ++i) - { - nul_dbus_object_t *object = service->objects[i]; - - dbus_connection_register_object_path ( - service->connection, object->name, &vtable, object); + service->running = TRUE; + + return TRUE; } - service->running = TRUE; - - return TRUE; + return FALSE; } void @@ -909,12 +568,12 @@ nul_dbus_service_stop (nul_dbus_service_t *service) for (obj = service->objects; *obj != NULL; ++obj) { nul_dbus_object_t *object = *obj; - - dbus_connection_unregister_object_path ( + + connection_unregister_object ( service->connection, object->name); } - dbus_bus_release_name (service->connection, service->name, NULL); + connection_release_name (service->connection, service->name); service->running = FALSE; } @@ -1168,30 +827,20 @@ typedef struct nul_dbus_member_t *method; } InvokeInfo; -static void -on_reply (DBusPendingCall *pending, +static gboolean +on_reply (connection_t *connection, + DBusMessage *reply, gpointer data) { InvokeInfo *info = data; int n_outputs = info->method->n_outputs; nul_dbus_parameter_t **outputs; - DBusMessage *reply; nul_arg_t *args; nul_arg_t arg; char *err; if (!info->callback) - return; - - reply = dbus_pending_call_steal_reply (pending); - - if (!reply) - { - /* FIXME: can this happen? If it can, we should - * generate an error. - */ - return; - } + return TRUE; outputs = (nul_dbus_parameter_t **)&(info->method->parameters[info->method->n_inputs]); @@ -1209,6 +858,8 @@ on_reply (DBusPendingCall *pending, nul_fun_def_invoke (info->method->reply_fun, (nul_function_t)info->callback, args); nul_array_free (args); + + return TRUE; } /* Decodes strings like this: @@ -1301,10 +952,9 @@ nul_dbus_invoke (nul_dbus_service_t *service, nul_dbus_member_t *method; DBusMessage *message; DBusMessageIter iter; - DBusConnection *connection; + connection_t *connection; va_list args; InvokeInfo *info; - DBusPendingCall *pending; nul_dbus_parameter_t **p; g_return_if_fail (service != NULL); @@ -1377,10 +1027,15 @@ nul_dbus_invoke (nul_dbus_service_t *service, va_end (args); - connection = get_connection (service->type, NULL); + connection = service->connection; + + info = g_new0 (InvokeInfo, 1); + + info->callback = callback; + info->data = data; + info->method = method; - dbus_connection_send_with_reply (connection, message, &pending, -1); - if (!pending) + if (!connection_send_with_reply (connection, message, on_reply, info)) { /* FIXME: generate an error and call the callback */ @@ -1388,16 +1043,6 @@ nul_dbus_invoke (nul_dbus_service_t *service, * though it's not clear what we should do with that */ } - else - { - info = g_new0 (InvokeInfo, 1); - - info->callback = callback; - info->data = data; - info->method = method; - - dbus_pending_call_set_notify (pending, on_reply, info, g_free); - } dbus_message_unref (message); } diff --git a/libnul-private.h b/libnul-private.h index df7cf3e..a055b03 100644 --- a/libnul-private.h +++ b/libnul-private.h @@ -2,8 +2,9 @@ typedef struct connection_t connection_t; typedef struct message_t message_t; -typedef gboolean (* message_func_t) (DBusMessage *message, - nul_ptr_t data); +typedef gboolean (* message_func_t) (connection_t *connection, + DBusMessage *message, + nul_ptr_t data); connection_t *connection_new_session (void); connection_t *connection_new_system (void); @@ -13,3 +14,13 @@ void connection_register_object (connection_t *connection, nul_ptr_t data); void connection_unregister_object (connection_t *connection, const char *object_name); +gboolean connection_request_name (connection_t *connection, + const char *name); +void connection_send (connection_t *connection, + DBusMessage *message); +gboolean connection_send_with_reply (connection_t *connection, + DBusMessage *message, + message_func_t func, + gpointer data); +void connection_release_name (connection_t *connection, + const char * name); |