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