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 const 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 g_io_channel_unref (channel);
00290 }
00291
00292 static void
00293 connection_setup_remove_watch (ConnectionSetup *cs,
00294 DBusWatch *watch)
00295 {
00296 IOHandler *handler;
00297
00298 handler = dbus_watch_get_data (watch);
00299
00300 if (handler == NULL)
00301 return;
00302
00303 io_handler_destroy_source (handler);
00304 }
00305
00306 static void
00307 timeout_handler_source_finalized (gpointer data)
00308 {
00309 TimeoutHandler *handler;
00310
00311 handler = data;
00312
00313 if (handler->timeout)
00314 dbus_timeout_set_data (handler->timeout, NULL, NULL);
00315
00316 g_free (handler);
00317 }
00318
00319 static void
00320 timeout_handler_destroy_source (void *data)
00321 {
00322 TimeoutHandler *handler;
00323
00324 handler = data;
00325
00326 if (handler->source)
00327 {
00328 GSource *source = handler->source;
00329 handler->source = NULL;
00330 handler->cs->timeouts = g_slist_remove (handler->cs->timeouts, handler);
00331 g_source_destroy (source);
00332 g_source_unref (source);
00333 }
00334 }
00335
00336 static void
00337 timeout_handler_timeout_freed (void *data)
00338 {
00339 TimeoutHandler *handler;
00340
00341 handler = data;
00342
00343 handler->timeout = NULL;
00344
00345 timeout_handler_destroy_source (handler);
00346 }
00347
00348 static gboolean
00349 timeout_handler_dispatch (gpointer data)
00350 {
00351 TimeoutHandler *handler;
00352
00353 handler = data;
00354
00355 dbus_timeout_handle (handler->timeout);
00356
00357 return TRUE;
00358 }
00359
00360 static void
00361 connection_setup_add_timeout (ConnectionSetup *cs,
00362 DBusTimeout *timeout)
00363 {
00364 TimeoutHandler *handler;
00365
00366 if (!dbus_timeout_get_enabled (timeout))
00367 return;
00368
00369 g_assert (dbus_timeout_get_data (timeout) == NULL);
00370
00371 handler = g_new0 (TimeoutHandler, 1);
00372 handler->cs = cs;
00373 handler->timeout = timeout;
00374
00375 handler->source = g_timeout_source_new (dbus_timeout_get_interval (timeout));
00376 g_source_set_callback (handler->source, timeout_handler_dispatch, handler,
00377 timeout_handler_source_finalized);
00378 g_source_attach (handler->source, handler->cs->context);
00379
00380 cs->timeouts = g_slist_prepend (cs->timeouts, handler);
00381
00382 dbus_timeout_set_data (timeout, handler, timeout_handler_timeout_freed);
00383 }
00384
00385 static void
00386 connection_setup_remove_timeout (ConnectionSetup *cs,
00387 DBusTimeout *timeout)
00388 {
00389 TimeoutHandler *handler;
00390
00391 handler = dbus_timeout_get_data (timeout);
00392
00393 if (handler == NULL)
00394 return;
00395
00396 timeout_handler_destroy_source (handler);
00397 }
00398
00399 static void
00400 connection_setup_free (ConnectionSetup *cs)
00401 {
00402 while (cs->ios)
00403 io_handler_destroy_source (cs->ios->data);
00404
00405 while (cs->timeouts)
00406 timeout_handler_destroy_source (cs->timeouts->data);
00407
00408 if (cs->message_queue_source)
00409 {
00410 GSource *source;
00411
00412 source = cs->message_queue_source;
00413 cs->message_queue_source = NULL;
00414
00415 g_source_destroy (source);
00416 g_source_unref (source);
00417 }
00418
00419 g_main_context_unref (cs->context);
00420 g_free (cs);
00421 }
00422
00423 static dbus_bool_t
00424 add_watch (DBusWatch *watch,
00425 gpointer data)
00426 {
00427 ConnectionSetup *cs;
00428
00429 cs = data;
00430
00431 connection_setup_add_watch (cs, watch);
00432
00433 return TRUE;
00434 }
00435
00436 static void
00437 remove_watch (DBusWatch *watch,
00438 gpointer data)
00439 {
00440 ConnectionSetup *cs;
00441
00442 cs = data;
00443
00444 connection_setup_remove_watch (cs, watch);
00445 }
00446
00447 static void
00448 watch_toggled (DBusWatch *watch,
00449 void *data)
00450 {
00451
00452
00453
00454 if (dbus_watch_get_enabled (watch))
00455 add_watch (watch, data);
00456 else
00457 remove_watch (watch, data);
00458 }
00459
00460 static dbus_bool_t
00461 add_timeout (DBusTimeout *timeout,
00462 void *data)
00463 {
00464 ConnectionSetup *cs;
00465
00466 cs = data;
00467
00468 if (!dbus_timeout_get_enabled (timeout))
00469 return TRUE;
00470
00471 connection_setup_add_timeout (cs, timeout);
00472
00473 return TRUE;
00474 }
00475
00476 static void
00477 remove_timeout (DBusTimeout *timeout,
00478 void *data)
00479 {
00480 ConnectionSetup *cs;
00481
00482 cs = data;
00483
00484 connection_setup_remove_timeout (cs, timeout);
00485 }
00486
00487 static void
00488 timeout_toggled (DBusTimeout *timeout,
00489 void *data)
00490 {
00491
00492
00493
00494 if (dbus_timeout_get_enabled (timeout))
00495 add_timeout (timeout, data);
00496 else
00497 remove_timeout (timeout, data);
00498 }
00499
00500 static void
00501 wakeup_main (void *data)
00502 {
00503 ConnectionSetup *cs = data;
00504
00505 g_main_context_wakeup (cs->context);
00506 }
00507
00508
00509
00510 static ConnectionSetup*
00511 connection_setup_new_from_old (GMainContext *context,
00512 ConnectionSetup *old)
00513 {
00514 GSList *tmp;
00515 ConnectionSetup *cs;
00516
00517 g_assert (old->context != context);
00518
00519 cs = connection_setup_new (context, old->connection);
00520
00521 tmp = old->ios;
00522 while (tmp != NULL)
00523 {
00524 IOHandler *handler = tmp->data;
00525
00526 connection_setup_add_watch (cs, handler->watch);
00527
00528 tmp = tmp->next;
00529 }
00530
00531 tmp = old->timeouts;
00532 while (tmp != NULL)
00533 {
00534 TimeoutHandler *handler = tmp->data;
00535
00536 connection_setup_add_timeout (cs, handler->timeout);
00537
00538 tmp = tmp->next;
00539 }
00540
00541 return cs;
00542 }
00543
00545
00564 void
00565 dbus_connection_setup_with_g_main (DBusConnection *connection,
00566 GMainContext *context)
00567 {
00568 ConnectionSetup *old_setup;
00569 ConnectionSetup *cs;
00570
00571
00572
00573
00574 dbus_connection_allocate_data_slot (&connection_slot);
00575 if (connection_slot < 0)
00576 goto nomem;
00577
00578 if (context == NULL)
00579 context = g_main_context_default ();
00580
00581 cs = NULL;
00582
00583 old_setup = dbus_connection_get_data (connection, connection_slot);
00584 if (old_setup != NULL)
00585 {
00586 if (old_setup->context == context)
00587 return;
00588
00589 cs = connection_setup_new_from_old (context, old_setup);
00590
00591
00592 dbus_connection_set_data (connection, connection_slot, NULL, NULL);
00593 old_setup = NULL;
00594 }
00595
00596 if (cs == NULL)
00597 cs = connection_setup_new (context, connection);
00598
00599 if (!dbus_connection_set_data (connection, connection_slot, cs,
00600 (DBusFreeFunction)connection_setup_free))
00601 goto nomem;
00602
00603 if (!dbus_connection_set_watch_functions (connection,
00604 add_watch,
00605 remove_watch,
00606 watch_toggled,
00607 cs, NULL))
00608 goto nomem;
00609
00610 if (!dbus_connection_set_timeout_functions (connection,
00611 add_timeout,
00612 remove_timeout,
00613 timeout_toggled,
00614 cs, NULL))
00615 goto nomem;
00616
00617 dbus_connection_set_wakeup_main_function (connection,
00618 wakeup_main,
00619 cs, NULL);
00620
00621 return;
00622
00623 nomem:
00624 g_error ("Not enough memory to set up DBusConnection for use with GLib");
00625 }
00626
00640 void
00641 dbus_server_setup_with_g_main (DBusServer *server,
00642 GMainContext *context)
00643 {
00644 ConnectionSetup *old_setup;
00645 ConnectionSetup *cs;
00646
00647
00648
00649
00650 dbus_server_allocate_data_slot (&server_slot);
00651 if (server_slot < 0)
00652 goto nomem;
00653
00654 if (context == NULL)
00655 context = g_main_context_default ();
00656
00657 cs = NULL;
00658
00659 old_setup = dbus_server_get_data (server, server_slot);
00660 if (old_setup != NULL)
00661 {
00662 if (old_setup->context == context)
00663 return;
00664
00665 cs = connection_setup_new_from_old (context, old_setup);
00666
00667
00668 dbus_server_set_data (server, server_slot, NULL, NULL);
00669 old_setup = NULL;
00670 }
00671
00672 if (cs == NULL)
00673 cs = connection_setup_new (context, NULL);
00674
00675 if (!dbus_server_set_data (server, server_slot, cs,
00676 (DBusFreeFunction)connection_setup_free))
00677 goto nomem;
00678
00679 if (!dbus_server_set_watch_functions (server,
00680 add_watch,
00681 remove_watch,
00682 watch_toggled,
00683 cs, NULL))
00684 goto nomem;
00685
00686 if (!dbus_server_set_timeout_functions (server,
00687 add_timeout,
00688 remove_timeout,
00689 timeout_toggled,
00690 cs, NULL))
00691 goto nomem;
00692
00693 return;
00694
00695 nomem:
00696 g_error ("Not enough memory to set up DBusServer for use with GLib");
00697 }
00698
00710 DBusGConnection*
00711 dbus_g_bus_get (DBusBusType type,
00712 GError **error)
00713 {
00714 DBusConnection *connection;
00715 DBusError derror;
00716
00717 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
00718
00719 _dbus_g_value_types_init ();
00720
00721 dbus_error_init (&derror);
00722
00723 connection = dbus_bus_get (type, &derror);
00724 if (connection == NULL)
00725 {
00726 dbus_set_g_error (error, &derror);
00727 dbus_error_free (&derror);
00728 return NULL;
00729 }
00730
00731
00732 dbus_connection_setup_with_g_main (connection, NULL);
00733
00734 return DBUS_G_CONNECTION_FROM_CONNECTION (connection);
00735 }
00736
00738
00739 #ifdef DBUS_BUILD_TESTS
00740
00746 gboolean
00747 _dbus_gmain_test (const char *test_data_dir)
00748 {
00749 GType type;
00750 GType rectype;
00751
00752 g_type_init ();
00753 _dbus_g_value_types_init ();
00754
00755 rectype = dbus_g_type_get_collection ("GArray", G_TYPE_UINT);
00756 g_assert (rectype != G_TYPE_INVALID);
00757 g_assert (!strcmp (g_type_name (rectype), "GArray+guint"));
00758
00759 type = _dbus_gtype_from_signature ("au", TRUE);
00760 g_assert (type == rectype);
00761
00762 rectype = dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING);
00763 g_assert (rectype != G_TYPE_INVALID);
00764 g_assert (!strcmp (g_type_name (rectype), "GHashTable+gchararray+gchararray"));
00765
00766 type = _dbus_gtype_from_signature ("a{ss}", TRUE);
00767 g_assert (type == rectype);
00768
00769 type = _dbus_gtype_from_signature ("o", FALSE);
00770 g_assert (type == DBUS_TYPE_G_OBJECT_PATH);
00771 type = _dbus_gtype_from_signature ("o", TRUE);
00772 g_assert (type == DBUS_TYPE_G_OBJECT_PATH);
00773
00774 return TRUE;
00775 }
00776
00777 #endif