diff options
Diffstat (limited to 'glib/dbus-gmain.c')
| -rw-r--r-- | glib/dbus-gmain.c | 814 | 
1 files changed, 0 insertions, 814 deletions
diff --git a/glib/dbus-gmain.c b/glib/dbus-gmain.c deleted file mode 100644 index 54f868dd..00000000 --- a/glib/dbus-gmain.c +++ /dev/null @@ -1,814 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu" -*- */ -/* dbus-gmain.c GLib main loop integration - * - * Copyright (C) 2002, 2003 CodeFactory AB - * Copyright (C) 2005 Red Hat, Inc. - * - * Licensed under the Academic Free License version 2.1 - *  - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - *  - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA - * - */ - -#include <config.h> -#include <dbus/dbus-glib.h> -#include <dbus/dbus-glib-lowlevel.h> -#include "dbus-gtest.h" -#include "dbus-gutils.h" -#include "dbus-gvalue.h" -#include "dbus-gobject.h" -#include "dbus-gvalue-utils.h" -#include "dbus-gsignature.h" -#include <string.h> - -#include <libintl.h> -#define _(x) dgettext (GETTEXT_PACKAGE, x) -#define N_(x) x - -/** - * @defgroup DBusGLib GLib bindings - * @brief API for using D-BUS with GLib - * - * libdbus proper is a low-level API, these GLib bindings wrap libdbus - * with a much higher-level approach. The higher level approach is - * possible because GLib defines a main loop, an object/type system, - * and an out-of-memory handling policy (it exits the program). - * See http://www.gtk.org for GLib information. - * - * To manipulate remote objects, use #DBusGProxy. - */ - -/** - * @defgroup DBusGLibInternals GLib bindings implementation details - * @ingroup  DBusInternals - * @brief Implementation details of GLib bindings - * - * @{ - */ - -/** - * A GSource subclass for dispatching DBusConnection messages. - * We need this on top of the IO handlers, because sometimes - * there are messages to dispatch queued up but no IO pending. - */ -typedef struct -{ -  GSource source; /**< the parent GSource */ -  DBusConnection *connection; /**< the connection to dispatch */ -} DBusGMessageQueue; - -static gboolean message_queue_prepare  (GSource     *source, -                                        gint        *timeout); -static gboolean message_queue_check    (GSource     *source); -static gboolean message_queue_dispatch (GSource     *source, -                                        GSourceFunc  callback, -                                        gpointer     user_data); - -static const GSourceFuncs message_queue_funcs = { -  message_queue_prepare, -  message_queue_check, -  message_queue_dispatch, -  NULL -}; - -static gboolean -message_queue_prepare (GSource *source, -                       gint    *timeout) -{ -  DBusConnection *connection = ((DBusGMessageQueue *)source)->connection; -   -  *timeout = -1; - -  return (dbus_connection_get_dispatch_status (connection) == DBUS_DISPATCH_DATA_REMAINS);   -} - -static gboolean -message_queue_check (GSource *source) -{ -  return FALSE; -} - -static gboolean -message_queue_dispatch (GSource     *source, -                        GSourceFunc  callback, -                        gpointer     user_data) -{ -  DBusConnection *connection = ((DBusGMessageQueue *)source)->connection; - -  dbus_connection_ref (connection); - -  /* Only dispatch once - we don't want to starve other GSource */ -  dbus_connection_dispatch (connection); -   -  dbus_connection_unref (connection); - -  return TRUE; -} - -typedef struct -{ -  GMainContext *context;      /**< the main context */ -  GSList *ios;                /**< all IOHandler */ -  GSList *timeouts;           /**< all TimeoutHandler */ -  DBusConnection *connection; /**< NULL if this is really for a server not a connection */ -  GSource *message_queue_source; /**< DBusGMessageQueue */ -} ConnectionSetup; - - -typedef struct -{ -  ConnectionSetup *cs; -  GSource *source; -  DBusWatch *watch; -} IOHandler; - -typedef struct -{ -  ConnectionSetup *cs; -  GSource *source; -  DBusTimeout *timeout; -} TimeoutHandler; - -static dbus_int32_t connection_slot = -1; -static dbus_int32_t server_slot = -1; - -static ConnectionSetup* -connection_setup_new (GMainContext   *context, -                      DBusConnection *connection) -{ -  ConnectionSetup *cs; - -  cs = g_new0 (ConnectionSetup, 1); - -  g_assert (context != NULL); -   -  cs->context = context; -  g_main_context_ref (cs->context);   - -  if (connection) -    { -      cs->connection = connection; - -      cs->message_queue_source = g_source_new (&message_queue_funcs, -                                               sizeof (DBusGMessageQueue)); -      ((DBusGMessageQueue*)cs->message_queue_source)->connection = connection; -      g_source_attach (cs->message_queue_source, cs->context); -    } -   -  return cs; -} - -static void -io_handler_source_finalized (gpointer data) -{ -  IOHandler *handler; - -  handler = data; - -  if (handler->watch) -    dbus_watch_set_data (handler->watch, NULL, NULL); -   -  g_free (handler); -} - -static void -io_handler_destroy_source (void *data) -{ -  IOHandler *handler; - -  handler = data; - -  if (handler->source) -    { -      GSource *source = handler->source; -      handler->source = NULL; -      handler->cs->ios = g_slist_remove (handler->cs->ios, handler); -      g_source_destroy (source); -      g_source_unref (source); -    } -} - -static void -io_handler_watch_freed (void *data) -{ -  IOHandler *handler; - -  handler = data; - -  handler->watch = NULL; - -  io_handler_destroy_source (handler); -} - -static gboolean -io_handler_dispatch (GIOChannel   *source, -                     GIOCondition  condition, -                     gpointer      data) -{ -  IOHandler *handler; -  guint dbus_condition = 0; -  DBusConnection *connection; - -  handler = data; - -  connection = handler->cs->connection; -   -  if (connection) -    dbus_connection_ref (connection); -   -  if (condition & G_IO_IN) -    dbus_condition |= DBUS_WATCH_READABLE; -  if (condition & G_IO_OUT) -    dbus_condition |= DBUS_WATCH_WRITABLE; -  if (condition & G_IO_ERR) -    dbus_condition |= DBUS_WATCH_ERROR; -  if (condition & G_IO_HUP) -    dbus_condition |= DBUS_WATCH_HANGUP; - -  /* Note that we don't touch the handler after this, because -   * dbus may have disabled the watch and thus killed the -   * handler. -   */ -  dbus_watch_handle (handler->watch, dbus_condition); -  handler = NULL; - -  if (connection) -    dbus_connection_unref (connection); -   -  return TRUE; -} - -static void -connection_setup_add_watch (ConnectionSetup *cs, -                            DBusWatch       *watch) -{ -  guint flags; -  GIOCondition condition; -  GIOChannel *channel; -  IOHandler *handler; -   -  if (!dbus_watch_get_enabled (watch)) -    return; -   -  g_assert (dbus_watch_get_data (watch) == NULL); -   -  flags = dbus_watch_get_flags (watch); - -  condition = G_IO_ERR | G_IO_HUP; -  if (flags & DBUS_WATCH_READABLE) -    condition |= G_IO_IN; -  if (flags & DBUS_WATCH_WRITABLE) -    condition |= G_IO_OUT; - -  handler = g_new0 (IOHandler, 1); -  handler->cs = cs; -  handler->watch = watch; -   -  channel = g_io_channel_unix_new (dbus_watch_get_fd (watch)); -   -  handler->source = g_io_create_watch (channel, condition); -  g_source_set_callback (handler->source, (GSourceFunc) io_handler_dispatch, handler, -                         io_handler_source_finalized); -  g_source_attach (handler->source, cs->context); - -  cs->ios = g_slist_prepend (cs->ios, handler); -   -  dbus_watch_set_data (watch, handler, io_handler_watch_freed); -  g_io_channel_unref (channel); -} - -static void -connection_setup_remove_watch (ConnectionSetup *cs, -                               DBusWatch       *watch) -{ -  IOHandler *handler; - -  handler = dbus_watch_get_data (watch); - -  if (handler == NULL) -    return; -   -  io_handler_destroy_source (handler); -} - -static void -timeout_handler_source_finalized (gpointer data) -{ -  TimeoutHandler *handler; - -  handler = data; - -  if (handler->timeout) -    dbus_timeout_set_data (handler->timeout, NULL, NULL); -   -  g_free (handler); -} - -static void -timeout_handler_destroy_source (void *data) -{ -  TimeoutHandler *handler; - -  handler = data; - -  if (handler->source) -    { -      GSource *source = handler->source; -      handler->source = NULL; -      handler->cs->timeouts = g_slist_remove (handler->cs->timeouts, handler); -      g_source_destroy (source); -      g_source_unref (source); -    } -} - -static void -timeout_handler_timeout_freed (void *data) -{ -  TimeoutHandler *handler; - -  handler = data; - -  handler->timeout = NULL; - -  timeout_handler_destroy_source (handler); -} - -static gboolean -timeout_handler_dispatch (gpointer      data) -{ -  TimeoutHandler *handler; - -  handler = data; - -  dbus_timeout_handle (handler->timeout); -   -  return TRUE; -} - -static void -connection_setup_add_timeout (ConnectionSetup *cs, -                              DBusTimeout     *timeout) -{ -  TimeoutHandler *handler; -   -  if (!dbus_timeout_get_enabled (timeout)) -    return; -   -  g_assert (dbus_timeout_get_data (timeout) == NULL); - -  handler = g_new0 (TimeoutHandler, 1); -  handler->cs = cs; -  handler->timeout = timeout; - -  handler->source = g_timeout_source_new (dbus_timeout_get_interval (timeout)); -  g_source_set_callback (handler->source, timeout_handler_dispatch, handler, -                         timeout_handler_source_finalized); -  g_source_attach (handler->source, handler->cs->context); - -  cs->timeouts = g_slist_prepend (cs->timeouts, handler); - -  dbus_timeout_set_data (timeout, handler, timeout_handler_timeout_freed); -} - -static void -connection_setup_remove_timeout (ConnectionSetup *cs, -                                 DBusTimeout       *timeout) -{ -  TimeoutHandler *handler; -   -  handler = dbus_timeout_get_data (timeout); - -  if (handler == NULL) -    return; -   -  timeout_handler_destroy_source (handler); -} - -static void -connection_setup_free (ConnectionSetup *cs) -{ -  while (cs->ios) -    io_handler_destroy_source (cs->ios->data); - -  while (cs->timeouts) -    timeout_handler_destroy_source (cs->timeouts->data); - -  if (cs->message_queue_source) -    { -      GSource *source; - -      source = cs->message_queue_source; -      cs->message_queue_source = NULL; - -      g_source_destroy (source); -      g_source_unref (source); -    } -   -  g_main_context_unref (cs->context); -  g_free (cs); -} - -static dbus_bool_t -add_watch (DBusWatch *watch, -	   gpointer   data) -{ -  ConnectionSetup *cs; - -  cs = data; - -  connection_setup_add_watch (cs, watch); -   -  return TRUE; -} - -static void -remove_watch (DBusWatch *watch, -	      gpointer   data) -{ -  ConnectionSetup *cs; - -  cs = data; - -  connection_setup_remove_watch (cs, watch); -} - -static void -watch_toggled (DBusWatch *watch, -               void      *data) -{ -  /* Because we just exit on OOM, enable/disable is -   * no different from add/remove -   */ -  if (dbus_watch_get_enabled (watch)) -    add_watch (watch, data); -  else -    remove_watch (watch, data); -} - -static dbus_bool_t -add_timeout (DBusTimeout *timeout, -	     void        *data) -{ -  ConnectionSetup *cs; - -  cs = data; -   -  if (!dbus_timeout_get_enabled (timeout)) -    return TRUE; - -  connection_setup_add_timeout (cs, timeout); - -  return TRUE; -} - -static void -remove_timeout (DBusTimeout *timeout, -		void        *data) -{ -  ConnectionSetup *cs; - -  cs = data; - -  connection_setup_remove_timeout (cs, timeout); -} - -static void -timeout_toggled (DBusTimeout *timeout, -                 void        *data) -{ -  /* Because we just exit on OOM, enable/disable is -   * no different from add/remove -   */ -  if (dbus_timeout_get_enabled (timeout)) -    add_timeout (timeout, data); -  else -    remove_timeout (timeout, data); -} - -static void -wakeup_main (void *data) -{ -  ConnectionSetup *cs = data; - -  g_main_context_wakeup (cs->context); -} - - -/* Move to a new context */ -static ConnectionSetup* -connection_setup_new_from_old (GMainContext    *context, -                               ConnectionSetup *old) -{ -  GSList *tmp; -  ConnectionSetup *cs; - -  g_assert (old->context != context); -   -  cs = connection_setup_new (context, old->connection); -   -  tmp = old->ios; -  while (tmp != NULL) -    { -      IOHandler *handler = tmp->data; - -      connection_setup_add_watch (cs, handler->watch); -       -      tmp = tmp->next; -    } - -  tmp = old->timeouts; -  while (tmp != NULL) -    { -      TimeoutHandler *handler = tmp->data; - -      connection_setup_add_timeout (cs, handler->timeout); -       -      tmp = tmp->next; -    } - -  return cs; -} - -/** @} */ /* End of GLib bindings internals */ - -/** @addtogroup DBusGLib - * @{ - */ - -/** - * Sets the watch and timeout functions of a #DBusConnection - * to integrate the connection with the GLib main loop. - * Pass in #NULL for the #GMainContext unless you're - * doing something specialized. - * - * If called twice for the same context, does nothing the second - * time. If called once with context A and once with context B, - * context B replaces context A as the context monitoring the - * connection. - * - * @param connection the connection - * @param context the #GMainContext or #NULL for default context - */ -void -dbus_connection_setup_with_g_main (DBusConnection *connection, -				   GMainContext   *context) -{ -  ConnectionSetup *old_setup; -  ConnectionSetup *cs; -   -  /* FIXME we never free the slot, so its refcount just keeps growing, -   * which is kind of broken. -   */ -  dbus_connection_allocate_data_slot (&connection_slot); -  if (connection_slot < 0) -    goto nomem; - -  if (context == NULL) -    context = g_main_context_default (); - -  cs = NULL; -   -  old_setup = dbus_connection_get_data (connection, connection_slot); -  if (old_setup != NULL) -    { -      if (old_setup->context == context) -        return; /* nothing to do */ - -      cs = connection_setup_new_from_old (context, old_setup); -       -      /* Nuke the old setup */ -      dbus_connection_set_data (connection, connection_slot, NULL, NULL); -      old_setup = NULL; -    } - -  if (cs == NULL) -    cs = connection_setup_new (context, connection); - -  if (!dbus_connection_set_data (connection, connection_slot, cs, -                                 (DBusFreeFunction)connection_setup_free)) -    goto nomem; -   -  if (!dbus_connection_set_watch_functions (connection, -                                            add_watch, -                                            remove_watch, -                                            watch_toggled, -                                            cs, NULL)) -    goto nomem; - -  if (!dbus_connection_set_timeout_functions (connection, -                                              add_timeout, -                                              remove_timeout, -                                              timeout_toggled, -                                              cs, NULL)) -    goto nomem; -     -  dbus_connection_set_wakeup_main_function (connection, -					    wakeup_main, -					    cs, NULL); -       -  return; - - nomem: -  g_error ("Not enough memory to set up DBusConnection for use with GLib"); -} - -/** - * Sets the watch and timeout functions of a #DBusServer - * to integrate the server with the GLib main loop. - * In most cases the context argument should be #NULL. - * - * If called twice for the same context, does nothing the second - * time. If called once with context A and once with context B, - * context B replaces context A as the context monitoring the - * connection. - * - * @param server the server - * @param context the #GMainContext or #NULL for default - */ -void -dbus_server_setup_with_g_main (DBusServer   *server, -                               GMainContext *context) -{ -  ConnectionSetup *old_setup; -  ConnectionSetup *cs; -   -  /* FIXME we never free the slot, so its refcount just keeps growing, -   * which is kind of broken. -   */ -  dbus_server_allocate_data_slot (&server_slot); -  if (server_slot < 0) -    goto nomem; - -  if (context == NULL) -    context = g_main_context_default (); - -  cs = NULL; -   -  old_setup = dbus_server_get_data (server, server_slot); -  if (old_setup != NULL) -    { -      if (old_setup->context == context) -        return; /* nothing to do */ - -      cs = connection_setup_new_from_old (context, old_setup); -       -      /* Nuke the old setup */ -      dbus_server_set_data (server, server_slot, NULL, NULL); -      old_setup = NULL; -    } - -  if (cs == NULL) -    cs = connection_setup_new (context, NULL); - -  if (!dbus_server_set_data (server, server_slot, cs, -                             (DBusFreeFunction)connection_setup_free)) -    goto nomem; -   -  if (!dbus_server_set_watch_functions (server, -                                        add_watch, -                                        remove_watch, -                                        watch_toggled, -                                        cs, NULL)) -    goto nomem; - -  if (!dbus_server_set_timeout_functions (server, -                                          add_timeout, -                                          remove_timeout, -                                          timeout_toggled, -                                          cs, NULL)) -    goto nomem; -       -  return; - - nomem: -  g_error ("Not enough memory to set up DBusServer for use with GLib"); -} - -/** - * Returns a connection to the given address. - * - * (Internally, calls dbus_connection_open() then calls - * dbus_connection_setup_with_g_main() on the result.) - * - * @param address address of the connection to open - * @param error address where an error can be returned. - * @returns a DBusConnection - */ -DBusGConnection* -dbus_g_connection_open (const gchar  *address, -                        GError      **error) -{ -  DBusConnection *connection; -  DBusError derror; - -  g_return_val_if_fail (error == NULL || *error == NULL, NULL); - -  _dbus_g_value_types_init (); - -  dbus_error_init (&derror); - -  connection = dbus_connection_open (address, &derror); -  if (connection == NULL) -    { -      dbus_set_g_error (error, &derror); -      dbus_error_free (&derror); -      return NULL; -    } - -  /* does nothing if it's already been done */ -  dbus_connection_setup_with_g_main (connection, NULL); - -  return DBUS_G_CONNECTION_FROM_CONNECTION (connection); -} - -/** - * Returns a connection to the given bus. The connection is a global variable - * shared with other callers of this function. - *  - * (Internally, calls dbus_bus_get() then calls - * dbus_connection_setup_with_g_main() on the result.) - * - * @param type bus type - * @param error address where an error can be returned. - * @returns a DBusConnection - */ -DBusGConnection* -dbus_g_bus_get (DBusBusType     type, -                GError        **error) -{ -  DBusConnection *connection; -  DBusError derror; - -  g_return_val_if_fail (error == NULL || *error == NULL, NULL); - -  _dbus_g_value_types_init (); -   -  dbus_error_init (&derror); - -  connection = dbus_bus_get (type, &derror); -  if (connection == NULL) -    { -      dbus_set_g_error (error, &derror); -      dbus_error_free (&derror); -      return NULL; -    } - -  /* does nothing if it's already been done */ -  dbus_connection_setup_with_g_main (connection, NULL); - -  return DBUS_G_CONNECTION_FROM_CONNECTION (connection); -} - -/** @} */ /* end of public API */ - -#ifdef DBUS_BUILD_TESTS - -/** - * @ingroup DBusGLibInternals - * Unit test for GLib main loop integration - * @returns #TRUE on success. - */ -gboolean -_dbus_gmain_test (const char *test_data_dir) -{ -  GType type; -  GType rectype; - -  g_type_init (); -  _dbus_g_value_types_init (); - -  rectype = dbus_g_type_get_collection ("GArray", G_TYPE_UINT); -  g_assert (rectype != G_TYPE_INVALID); -  g_assert (!strcmp (g_type_name (rectype), "GArray_guint_")); - -  type = _dbus_gtype_from_signature ("au", TRUE); -  g_assert (type == rectype); - -  rectype = dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING); -  g_assert (rectype != G_TYPE_INVALID); -  g_assert (!strcmp (g_type_name (rectype), "GHashTable_gchararray+gchararray_")); - -  type = _dbus_gtype_from_signature ("a{ss}", TRUE); -  g_assert (type == rectype); - -  type = _dbus_gtype_from_signature ("o", FALSE); -  g_assert (type == DBUS_TYPE_G_OBJECT_PATH); -  type = _dbus_gtype_from_signature ("o", TRUE); -  g_assert (type == DBUS_TYPE_G_OBJECT_PATH); -   -  return TRUE; -} - -#endif /* DBUS_BUILD_TESTS */  | 
