00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <config.h>
00026 #include <dbus/dbus-glib.h>
00027 #include <dbus/dbus-glib-lowlevel.h>
00028 #include "dbus-gtest.h"
00029 #include "dbus-gutils.h"
00030 #include "dbus-gvalue.h"
00031 #include "dbus-gobject.h"
00032 #include "dbus-gvalue-utils.h"
00033 #include "dbus-gsignature.h"
00034 #include <string.h>
00035
00036 #include <libintl.h>
00037 #define _(x) dgettext (GETTEXT_PACKAGE, x)
00038 #define N_(x) x
00039
00054 typedef struct
00055 {
00056 GSource source;
00057 DBusConnection *connection;
00058 } DBusGMessageQueue;
00059
00060 static gboolean message_queue_prepare (GSource *source,
00061 gint *timeout);
00062 static gboolean message_queue_check (GSource *source);
00063 static gboolean message_queue_dispatch (GSource *source,
00064 GSourceFunc callback,
00065 gpointer user_data);
00066
00067 static const GSourceFuncs message_queue_funcs = {
00068 message_queue_prepare,
00069 message_queue_check,
00070 message_queue_dispatch,
00071 NULL
00072 };
00073
00074 static gboolean
00075 message_queue_prepare (GSource *source,
00076 gint *timeout)
00077 {
00078 DBusConnection *connection = ((DBusGMessageQueue *)source)->connection;
00079
00080 *timeout = -1;
00081
00082 return (dbus_connection_get_dispatch_status (connection) == DBUS_DISPATCH_DATA_REMAINS);
00083 }
00084
00085 static gboolean
00086 message_queue_check (GSource *source)
00087 {
00088 return FALSE;
00089 }
00090
00091 static gboolean
00092 message_queue_dispatch (GSource *source,
00093 GSourceFunc callback,
00094 gpointer user_data)
00095 {
00096 DBusConnection *connection = ((DBusGMessageQueue *)source)->connection;
00097
00098 dbus_connection_ref (connection);
00099
00100
00101 dbus_connection_dispatch (connection);
00102
00103 dbus_connection_unref (connection);
00104
00105 return TRUE;
00106 }
00107
00108 typedef struct
00109 {
00110 GMainContext *context;
00111 GSList *ios;
00112 GSList *timeouts;
00113 DBusConnection *connection;
00114 GSource *message_queue_source;
00115 } ConnectionSetup;
00116
00117
00118 typedef struct
00119 {
00120 ConnectionSetup *cs;
00121 GSource *source;
00122 DBusWatch *watch;
00123 } IOHandler;
00124
00125 typedef struct
00126 {
00127 ConnectionSetup *cs;
00128 GSource *source;
00129 DBusTimeout *timeout;
00130 } TimeoutHandler;
00131
00132 dbus_int32_t _dbus_gmain_connection_slot = -1;
00133 static dbus_int32_t server_slot = -1;
00134
00135 static ConnectionSetup*
00136 connection_setup_new (GMainContext *context,
00137 DBusConnection *connection)
00138 {
00139 ConnectionSetup *cs;
00140
00141 cs = g_new0 (ConnectionSetup, 1);
00142
00143 g_assert (context != NULL);
00144
00145 cs->context = context;
00146 g_main_context_ref (cs->context);
00147
00148 if (connection)
00149 {
00150 cs->connection = connection;
00151
00152 cs->message_queue_source = g_source_new ((GSourceFuncs *) &message_queue_funcs,
00153 sizeof (DBusGMessageQueue));
00154 ((DBusGMessageQueue*)cs->message_queue_source)->connection = connection;
00155 g_source_attach (cs->message_queue_source, cs->context);
00156 g_source_set_priority (cs->message_queue_source, G_PRIORITY_HIGH);
00157 }
00158
00159 return cs;
00160 }
00161
00162 static void
00163 io_handler_source_finalized (gpointer data)
00164 {
00165 IOHandler *handler;
00166
00167 handler = data;
00168
00169 if (handler->watch)
00170 dbus_watch_set_data (handler->watch, NULL, NULL);
00171
00172 g_free (handler);
00173 }
00174
00175 static void
00176 io_handler_destroy_source (void *data)
00177 {
00178 IOHandler *handler;
00179
00180 handler = data;
00181
00182 if (handler->source)
00183 {
00184 GSource *source = handler->source;
00185 handler->source = NULL;
00186 handler->cs->ios = g_slist_remove (handler->cs->ios, handler);
00187 g_source_destroy (source);
00188 g_source_unref (source);
00189 }
00190 }
00191
00192 static void
00193 io_handler_watch_freed (void *data)
00194 {
00195 IOHandler *handler;
00196
00197 handler = data;
00198
00199 handler->watch = NULL;
00200
00201 io_handler_destroy_source (handler);
00202 }
00203
00204 static gboolean
00205 io_handler_dispatch (GIOChannel *source,
00206 GIOCondition condition,
00207 gpointer data)
00208 {
00209 IOHandler *handler;
00210 guint dbus_condition = 0;
00211 DBusConnection *connection;
00212
00213 handler = data;
00214
00215 connection = handler->cs->connection;
00216
00217 if (connection)
00218 dbus_connection_ref (connection);
00219
00220 if (condition & G_IO_IN)
00221 dbus_condition |= DBUS_WATCH_READABLE;
00222 if (condition & G_IO_OUT)
00223 dbus_condition |= DBUS_WATCH_WRITABLE;
00224 if (condition & G_IO_ERR)
00225 dbus_condition |= DBUS_WATCH_ERROR;
00226 if (condition & G_IO_HUP)
00227 dbus_condition |= DBUS_WATCH_HANGUP;
00228
00229
00230
00231
00232
00233 dbus_watch_handle (handler->watch, dbus_condition);
00234 handler = NULL;
00235
00236 if (connection)
00237 dbus_connection_unref (connection);
00238
00239 return TRUE;
00240 }
00241
00242 static void
00243 connection_setup_add_watch (ConnectionSetup *cs,
00244 DBusWatch *watch)
00245 {
00246 guint flags;
00247 GIOCondition condition;
00248 GIOChannel *channel;
00249 IOHandler *handler;
00250
00251 if (!dbus_watch_get_enabled (watch))
00252 return;
00253
00254 g_assert (dbus_watch_get_data (watch) == NULL);
00255
00256 flags = dbus_watch_get_flags (watch);
00257
00258 condition = G_IO_ERR | G_IO_HUP;
00259 if (flags & DBUS_WATCH_READABLE)
00260 condition |= G_IO_IN;
00261 if (flags & DBUS_WATCH_WRITABLE)
00262 condition |= G_IO_OUT;
00263
00264 handler = g_new0 (IOHandler, 1);
00265 handler->cs = cs;
00266 handler->watch = watch;
00267
00268 channel = g_io_channel_unix_new (dbus_watch_get_fd (watch));
00269
00270 handler->source = g_io_create_watch (channel, condition);
00271 g_source_set_callback (handler->source, (GSourceFunc) io_handler_dispatch, handler,
00272 io_handler_source_finalized);
00273 g_source_attach (handler->source, cs->context);
00274 g_source_set_priority (handler->source, G_PRIORITY_HIGH);
00275
00276 cs->ios = g_slist_prepend (cs->ios, handler);
00277
00278 dbus_watch_set_data (watch, handler, io_handler_watch_freed);
00279 g_io_channel_unref (channel);
00280 }
00281
00282 static void
00283 connection_setup_remove_watch (ConnectionSetup *cs,
00284 DBusWatch *watch)
00285 {
00286 IOHandler *handler;
00287
00288 handler = dbus_watch_get_data (watch);
00289
00290 if (handler == NULL)
00291 return;
00292
00293 io_handler_destroy_source (handler);
00294 }
00295
00296 static void
00297 timeout_handler_source_finalized (gpointer data)
00298 {
00299 TimeoutHandler *handler;
00300
00301 handler = data;
00302
00303 if (handler->timeout)
00304 dbus_timeout_set_data (handler->timeout, NULL, NULL);
00305
00306 g_free (handler);
00307 }
00308
00309 static void
00310 timeout_handler_destroy_source (void *data)
00311 {
00312 TimeoutHandler *handler;
00313
00314 handler = data;
00315
00316 if (handler->source)
00317 {
00318 GSource *source = handler->source;
00319 handler->source = NULL;
00320 handler->cs->timeouts = g_slist_remove (handler->cs->timeouts, handler);
00321 g_source_destroy (source);
00322 g_source_unref (source);
00323 }
00324 }
00325
00326 static void
00327 timeout_handler_timeout_freed (void *data)
00328 {
00329 TimeoutHandler *handler;
00330
00331 handler = data;
00332
00333 handler->timeout = NULL;
00334
00335 timeout_handler_destroy_source (handler);
00336 }
00337
00338 static gboolean
00339 timeout_handler_dispatch (gpointer data)
00340 {
00341 TimeoutHandler *handler;
00342
00343 handler = data;
00344
00345 dbus_timeout_handle (handler->timeout);
00346
00347 return TRUE;
00348 }
00349
00350 static void
00351 connection_setup_add_timeout (ConnectionSetup *cs,
00352 DBusTimeout *timeout)
00353 {
00354 TimeoutHandler *handler;
00355
00356 if (!dbus_timeout_get_enabled (timeout))
00357 return;
00358
00359 g_assert (dbus_timeout_get_data (timeout) == NULL);
00360
00361 handler = g_new0 (TimeoutHandler, 1);
00362 handler->cs = cs;
00363 handler->timeout = timeout;
00364
00365 handler->source = g_timeout_source_new (dbus_timeout_get_interval (timeout));
00366 g_source_set_callback (handler->source, timeout_handler_dispatch, handler,
00367 timeout_handler_source_finalized);
00368 g_source_attach (handler->source, handler->cs->context);
00369
00370 cs->timeouts = g_slist_prepend (cs->timeouts, handler);
00371
00372 dbus_timeout_set_data (timeout, handler, timeout_handler_timeout_freed);
00373 }
00374
00375 static void
00376 connection_setup_remove_timeout (ConnectionSetup *cs,
00377 DBusTimeout *timeout)
00378 {
00379 TimeoutHandler *handler;
00380
00381 handler = dbus_timeout_get_data (timeout);
00382
00383 if (handler == NULL)
00384 return;
00385
00386 timeout_handler_destroy_source (handler);
00387 }
00388
00389 static void
00390 connection_setup_free (ConnectionSetup *cs)
00391 {
00392 while (cs->ios)
00393 io_handler_destroy_source (cs->ios->data);
00394
00395 while (cs->timeouts)
00396 timeout_handler_destroy_source (cs->timeouts->data);
00397
00398 if (cs->message_queue_source)
00399 {
00400 GSource *source;
00401
00402 source = cs->message_queue_source;
00403 cs->message_queue_source = NULL;
00404
00405 g_source_destroy (source);
00406 g_source_unref (source);
00407 }
00408
00409 g_main_context_unref (cs->context);
00410 g_free (cs);
00411 }
00412
00413 static dbus_bool_t
00414 add_watch (DBusWatch *watch,
00415 gpointer data)
00416 {
00417 ConnectionSetup *cs;
00418
00419 cs = data;
00420
00421 connection_setup_add_watch (cs, watch);
00422
00423 return TRUE;
00424 }
00425
00426 static void
00427 remove_watch (DBusWatch *watch,
00428 gpointer data)
00429 {
00430 ConnectionSetup *cs;
00431
00432 cs = data;
00433
00434 connection_setup_remove_watch (cs, watch);
00435 }
00436
00437 static void
00438 watch_toggled (DBusWatch *watch,
00439 void *data)
00440 {
00441
00442
00443
00444 if (dbus_watch_get_enabled (watch))
00445 add_watch (watch, data);
00446 else
00447 remove_watch (watch, data);
00448 }
00449
00450 static dbus_bool_t
00451 add_timeout (DBusTimeout *timeout,
00452 void *data)
00453 {
00454 ConnectionSetup *cs;
00455
00456 cs = data;
00457
00458 if (!dbus_timeout_get_enabled (timeout))
00459 return TRUE;
00460
00461 connection_setup_add_timeout (cs, timeout);
00462
00463 return TRUE;
00464 }
00465
00466 static void
00467 remove_timeout (DBusTimeout *timeout,
00468 void *data)
00469 {
00470 ConnectionSetup *cs;
00471
00472 cs = data;
00473
00474 connection_setup_remove_timeout (cs, timeout);
00475 }
00476
00477 static void
00478 timeout_toggled (DBusTimeout *timeout,
00479 void *data)
00480 {
00481
00482
00483
00484 if (dbus_timeout_get_enabled (timeout))
00485 add_timeout (timeout, data);
00486 else
00487 remove_timeout (timeout, data);
00488 }
00489
00490 static void
00491 wakeup_main (void *data)
00492 {
00493 ConnectionSetup *cs = data;
00494
00495 g_main_context_wakeup (cs->context);
00496 }
00497
00498
00499
00500 static ConnectionSetup*
00501 connection_setup_new_from_old (GMainContext *context,
00502 ConnectionSetup *old)
00503 {
00504 GSList *tmp;
00505 ConnectionSetup *cs;
00506
00507 g_assert (old->context != context);
00508
00509 cs = connection_setup_new (context, old->connection);
00510
00511 tmp = old->ios;
00512 while (tmp != NULL)
00513 {
00514 IOHandler *handler = tmp->data;
00515
00516 connection_setup_add_watch (cs, handler->watch);
00517
00518 tmp = tmp->next;
00519 }
00520
00521 tmp = old->timeouts;
00522 while (tmp != NULL)
00523 {
00524 TimeoutHandler *handler = tmp->data;
00525
00526 connection_setup_add_timeout (cs, handler->timeout);
00527
00528 tmp = tmp->next;
00529 }
00530
00531 return cs;
00532 }
00533
00535
00555 void
00556 dbus_connection_setup_with_g_main (DBusConnection *connection,
00557 GMainContext *context)
00558 {
00559 ConnectionSetup *old_setup;
00560 ConnectionSetup *cs;
00561
00562
00563
00564
00565 dbus_connection_allocate_data_slot (&_dbus_gmain_connection_slot);
00566 if (_dbus_gmain_connection_slot < 0)
00567 goto nomem;
00568
00569 if (context == NULL)
00570 context = g_main_context_default ();
00571
00572 cs = NULL;
00573
00574 old_setup = dbus_connection_get_data (connection, _dbus_gmain_connection_slot);
00575 if (old_setup != NULL)
00576 {
00577 if (old_setup->context == context)
00578 return;
00579
00580 cs = connection_setup_new_from_old (context, old_setup);
00581
00582
00583 dbus_connection_set_data (connection, _dbus_gmain_connection_slot, NULL, NULL);
00584 old_setup = NULL;
00585 }
00586
00587 if (cs == NULL)
00588 cs = connection_setup_new (context, connection);
00589
00590 if (!dbus_connection_set_data (connection, _dbus_gmain_connection_slot, cs,
00591 (DBusFreeFunction)connection_setup_free))
00592 goto nomem;
00593
00594 if (!dbus_connection_set_watch_functions (connection,
00595 add_watch,
00596 remove_watch,
00597 watch_toggled,
00598 cs, NULL))
00599 goto nomem;
00600
00601 if (!dbus_connection_set_timeout_functions (connection,
00602 add_timeout,
00603 remove_timeout,
00604 timeout_toggled,
00605 cs, NULL))
00606 goto nomem;
00607
00608 dbus_connection_set_wakeup_main_function (connection,
00609 wakeup_main,
00610 cs, NULL);
00611
00612 return;
00613
00614 nomem:
00615 g_error ("Not enough memory to set up DBusConnection for use with GLib");
00616 }
00617
00632 void
00633 dbus_server_setup_with_g_main (DBusServer *server,
00634 GMainContext *context)
00635 {
00636 ConnectionSetup *old_setup;
00637 ConnectionSetup *cs;
00638
00639
00640
00641
00642 dbus_server_allocate_data_slot (&server_slot);
00643 if (server_slot < 0)
00644 goto nomem;
00645
00646 if (context == NULL)
00647 context = g_main_context_default ();
00648
00649 cs = NULL;
00650
00651 old_setup = dbus_server_get_data (server, server_slot);
00652 if (old_setup != NULL)
00653 {
00654 if (old_setup->context == context)
00655 return;
00656
00657 cs = connection_setup_new_from_old (context, old_setup);
00658
00659
00660 dbus_server_set_data (server, server_slot, NULL, NULL);
00661 old_setup = NULL;
00662 }
00663
00664 if (cs == NULL)
00665 cs = connection_setup_new (context, NULL);
00666
00667 if (!dbus_server_set_data (server, server_slot, cs,
00668 (DBusFreeFunction)connection_setup_free))
00669 goto nomem;
00670
00671 if (!dbus_server_set_watch_functions (server,
00672 add_watch,
00673 remove_watch,
00674 watch_toggled,
00675 cs, NULL))
00676 goto nomem;
00677
00678 if (!dbus_server_set_timeout_functions (server,
00679 add_timeout,
00680 remove_timeout,
00681 timeout_toggled,
00682 cs, NULL))
00683 goto nomem;
00684
00685 return;
00686
00687 nomem:
00688 g_error ("Not enough memory to set up DBusServer for use with GLib");
00689 }
00690
00703 DBusGConnection*
00704 dbus_g_connection_open (const gchar *address,
00705 GError **error)
00706 {
00707 DBusConnection *connection;
00708 DBusError derror;
00709
00710 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
00711
00712 _dbus_g_value_types_init ();
00713
00714 dbus_error_init (&derror);
00715
00716 connection = dbus_connection_open (address, &derror);
00717 if (connection == NULL)
00718 {
00719 dbus_set_g_error (error, &derror);
00720 dbus_error_free (&derror);
00721 return NULL;
00722 }
00723
00724
00725 dbus_connection_setup_with_g_main (connection, NULL);
00726
00727 return DBUS_G_CONNECTION_FROM_CONNECTION (connection);
00728 }
00729
00743 DBusGConnection*
00744 dbus_g_bus_get (DBusBusType type,
00745 GError **error)
00746 {
00747 DBusConnection *connection;
00748 DBusError derror;
00749
00750 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
00751
00752 _dbus_g_value_types_init ();
00753
00754 dbus_error_init (&derror);
00755
00756 connection = dbus_bus_get (type, &derror);
00757 if (connection == NULL)
00758 {
00759 dbus_set_g_error (error, &derror);
00760 dbus_error_free (&derror);
00761 return NULL;
00762 }
00763
00764
00765 dbus_connection_setup_with_g_main (connection, NULL);
00766
00767 return DBUS_G_CONNECTION_FROM_CONNECTION (connection);
00768 }
00769
00771
00772 #ifdef DBUS_BUILD_TESTS
00773
00779 gboolean
00780 _dbus_gmain_test (const char *test_data_dir)
00781 {
00782 GType type;
00783 GType rectype;
00784
00785 g_type_init ();
00786 _dbus_g_value_types_init ();
00787
00788 rectype = dbus_g_type_get_collection ("GArray", G_TYPE_UINT);
00789 g_assert (rectype != G_TYPE_INVALID);
00790 g_assert (!strcmp (g_type_name (rectype), "GArray_guint_"));
00791
00792 type = _dbus_gtype_from_signature ("au", TRUE);
00793 g_assert (type == rectype);
00794
00795 rectype = dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING);
00796 g_assert (rectype != G_TYPE_INVALID);
00797 g_assert (!strcmp (g_type_name (rectype), "GHashTable_gchararray+gchararray_"));
00798
00799 type = _dbus_gtype_from_signature ("a{ss}", TRUE);
00800 g_assert (type == rectype);
00801
00802 type = _dbus_gtype_from_signature ("o", FALSE);
00803 g_assert (type == DBUS_TYPE_G_OBJECT_PATH);
00804 type = _dbus_gtype_from_signature ("o", TRUE);
00805 g_assert (type == DBUS_TYPE_G_OBJECT_PATH);
00806
00807 return TRUE;
00808 }
00809
00810 #endif