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 }
00157
00158 return cs;
00159 }
00160
00161 static void
00162 io_handler_source_finalized (gpointer data)
00163 {
00164 IOHandler *handler;
00165
00166 handler = data;
00167
00168 if (handler->watch)
00169 dbus_watch_set_data (handler->watch, NULL, NULL);
00170
00171 g_free (handler);
00172 }
00173
00174 static void
00175 io_handler_destroy_source (void *data)
00176 {
00177 IOHandler *handler;
00178
00179 handler = data;
00180
00181 if (handler->source)
00182 {
00183 GSource *source = handler->source;
00184 handler->source = NULL;
00185 handler->cs->ios = g_slist_remove (handler->cs->ios, handler);
00186 g_source_destroy (source);
00187 g_source_unref (source);
00188 }
00189 }
00190
00191 static void
00192 io_handler_watch_freed (void *data)
00193 {
00194 IOHandler *handler;
00195
00196 handler = data;
00197
00198 handler->watch = NULL;
00199
00200 io_handler_destroy_source (handler);
00201 }
00202
00203 static gboolean
00204 io_handler_dispatch (GIOChannel *source,
00205 GIOCondition condition,
00206 gpointer data)
00207 {
00208 IOHandler *handler;
00209 guint dbus_condition = 0;
00210 DBusConnection *connection;
00211
00212 handler = data;
00213
00214 connection = handler->cs->connection;
00215
00216 if (connection)
00217 dbus_connection_ref (connection);
00218
00219 if (condition & G_IO_IN)
00220 dbus_condition |= DBUS_WATCH_READABLE;
00221 if (condition & G_IO_OUT)
00222 dbus_condition |= DBUS_WATCH_WRITABLE;
00223 if (condition & G_IO_ERR)
00224 dbus_condition |= DBUS_WATCH_ERROR;
00225 if (condition & G_IO_HUP)
00226 dbus_condition |= DBUS_WATCH_HANGUP;
00227
00228
00229
00230
00231
00232 dbus_watch_handle (handler->watch, dbus_condition);
00233 handler = NULL;
00234
00235 if (connection)
00236 dbus_connection_unref (connection);
00237
00238 return TRUE;
00239 }
00240
00241 static void
00242 connection_setup_add_watch (ConnectionSetup *cs,
00243 DBusWatch *watch)
00244 {
00245 guint flags;
00246 GIOCondition condition;
00247 GIOChannel *channel;
00248 IOHandler *handler;
00249
00250 if (!dbus_watch_get_enabled (watch))
00251 return;
00252
00253 g_assert (dbus_watch_get_data (watch) == NULL);
00254
00255 flags = dbus_watch_get_flags (watch);
00256
00257 condition = G_IO_ERR | G_IO_HUP;
00258 if (flags & DBUS_WATCH_READABLE)
00259 condition |= G_IO_IN;
00260 if (flags & DBUS_WATCH_WRITABLE)
00261 condition |= G_IO_OUT;
00262
00263 handler = g_new0 (IOHandler, 1);
00264 handler->cs = cs;
00265 handler->watch = watch;
00266
00267 channel = g_io_channel_unix_new (dbus_watch_get_unix_fd (watch));
00268
00269 handler->source = g_io_create_watch (channel, condition);
00270 g_source_set_callback (handler->source, (GSourceFunc) io_handler_dispatch, handler,
00271 io_handler_source_finalized);
00272 g_source_attach (handler->source, cs->context);
00273
00274 cs->ios = g_slist_prepend (cs->ios, handler);
00275
00276 dbus_watch_set_data (watch, handler, io_handler_watch_freed);
00277 g_io_channel_unref (channel);
00278 }
00279
00280 static void
00281 connection_setup_remove_watch (ConnectionSetup *cs,
00282 DBusWatch *watch)
00283 {
00284 IOHandler *handler;
00285
00286 handler = dbus_watch_get_data (watch);
00287
00288 if (handler == NULL)
00289 return;
00290
00291 io_handler_destroy_source (handler);
00292 }
00293
00294 static void
00295 timeout_handler_source_finalized (gpointer data)
00296 {
00297 TimeoutHandler *handler;
00298
00299 handler = data;
00300
00301 if (handler->timeout)
00302 dbus_timeout_set_data (handler->timeout, NULL, NULL);
00303
00304 g_free (handler);
00305 }
00306
00307 static void
00308 timeout_handler_destroy_source (void *data)
00309 {
00310 TimeoutHandler *handler;
00311
00312 handler = data;
00313
00314 if (handler->source)
00315 {
00316 GSource *source = handler->source;
00317 handler->source = NULL;
00318 handler->cs->timeouts = g_slist_remove (handler->cs->timeouts, handler);
00319 g_source_destroy (source);
00320 g_source_unref (source);
00321 }
00322 }
00323
00324 static void
00325 timeout_handler_timeout_freed (void *data)
00326 {
00327 TimeoutHandler *handler;
00328
00329 handler = data;
00330
00331 handler->timeout = NULL;
00332
00333 timeout_handler_destroy_source (handler);
00334 }
00335
00336 static gboolean
00337 timeout_handler_dispatch (gpointer data)
00338 {
00339 TimeoutHandler *handler;
00340
00341 handler = data;
00342
00343 dbus_timeout_handle (handler->timeout);
00344
00345 return TRUE;
00346 }
00347
00348 static void
00349 connection_setup_add_timeout (ConnectionSetup *cs,
00350 DBusTimeout *timeout)
00351 {
00352 TimeoutHandler *handler;
00353
00354 if (!dbus_timeout_get_enabled (timeout))
00355 return;
00356
00357 g_assert (dbus_timeout_get_data (timeout) == NULL);
00358
00359 handler = g_new0 (TimeoutHandler, 1);
00360 handler->cs = cs;
00361 handler->timeout = timeout;
00362
00363 handler->source = g_timeout_source_new (dbus_timeout_get_interval (timeout));
00364 g_source_set_callback (handler->source, timeout_handler_dispatch, handler,
00365 timeout_handler_source_finalized);
00366 g_source_attach (handler->source, handler->cs->context);
00367
00368 cs->timeouts = g_slist_prepend (cs->timeouts, handler);
00369
00370 dbus_timeout_set_data (timeout, handler, timeout_handler_timeout_freed);
00371 }
00372
00373 static void
00374 connection_setup_remove_timeout (ConnectionSetup *cs,
00375 DBusTimeout *timeout)
00376 {
00377 TimeoutHandler *handler;
00378
00379 handler = dbus_timeout_get_data (timeout);
00380
00381 if (handler == NULL)
00382 return;
00383
00384 timeout_handler_destroy_source (handler);
00385 }
00386
00387 static void
00388 connection_setup_free (ConnectionSetup *cs)
00389 {
00390 while (cs->ios)
00391 io_handler_destroy_source (cs->ios->data);
00392
00393 while (cs->timeouts)
00394 timeout_handler_destroy_source (cs->timeouts->data);
00395
00396 if (cs->message_queue_source)
00397 {
00398 GSource *source;
00399
00400 source = cs->message_queue_source;
00401 cs->message_queue_source = NULL;
00402
00403 g_source_destroy (source);
00404 g_source_unref (source);
00405 }
00406
00407 g_main_context_unref (cs->context);
00408 g_free (cs);
00409 }
00410
00411 static dbus_bool_t
00412 add_watch (DBusWatch *watch,
00413 gpointer data)
00414 {
00415 ConnectionSetup *cs;
00416
00417 cs = data;
00418
00419 connection_setup_add_watch (cs, watch);
00420
00421 return TRUE;
00422 }
00423
00424 static void
00425 remove_watch (DBusWatch *watch,
00426 gpointer data)
00427 {
00428 ConnectionSetup *cs;
00429
00430 cs = data;
00431
00432 connection_setup_remove_watch (cs, watch);
00433 }
00434
00435 static void
00436 watch_toggled (DBusWatch *watch,
00437 void *data)
00438 {
00439
00440
00441
00442 if (dbus_watch_get_enabled (watch))
00443 add_watch (watch, data);
00444 else
00445 remove_watch (watch, data);
00446 }
00447
00448 static dbus_bool_t
00449 add_timeout (DBusTimeout *timeout,
00450 void *data)
00451 {
00452 ConnectionSetup *cs;
00453
00454 cs = data;
00455
00456 if (!dbus_timeout_get_enabled (timeout))
00457 return TRUE;
00458
00459 connection_setup_add_timeout (cs, timeout);
00460
00461 return TRUE;
00462 }
00463
00464 static void
00465 remove_timeout (DBusTimeout *timeout,
00466 void *data)
00467 {
00468 ConnectionSetup *cs;
00469
00470 cs = data;
00471
00472 connection_setup_remove_timeout (cs, timeout);
00473 }
00474
00475 static void
00476 timeout_toggled (DBusTimeout *timeout,
00477 void *data)
00478 {
00479
00480
00481
00482 if (dbus_timeout_get_enabled (timeout))
00483 add_timeout (timeout, data);
00484 else
00485 remove_timeout (timeout, data);
00486 }
00487
00488 static void
00489 wakeup_main (void *data)
00490 {
00491 ConnectionSetup *cs = data;
00492
00493 g_main_context_wakeup (cs->context);
00494 }
00495
00496
00497
00498 static ConnectionSetup*
00499 connection_setup_new_from_old (GMainContext *context,
00500 ConnectionSetup *old)
00501 {
00502 GSList *tmp;
00503 ConnectionSetup *cs;
00504
00505 g_assert (old->context != context);
00506
00507 cs = connection_setup_new (context, old->connection);
00508
00509 tmp = old->ios;
00510 while (tmp != NULL)
00511 {
00512 IOHandler *handler = tmp->data;
00513
00514 connection_setup_add_watch (cs, handler->watch);
00515
00516 tmp = tmp->next;
00517 }
00518
00519 tmp = old->timeouts;
00520 while (tmp != NULL)
00521 {
00522 TimeoutHandler *handler = tmp->data;
00523
00524 connection_setup_add_timeout (cs, handler->timeout);
00525
00526 tmp = tmp->next;
00527 }
00528
00529 return cs;
00530 }
00531
00533
00553 void
00554 dbus_connection_setup_with_g_main (DBusConnection *connection,
00555 GMainContext *context)
00556 {
00557 ConnectionSetup *old_setup;
00558 ConnectionSetup *cs;
00559
00560
00561
00562
00563 dbus_connection_allocate_data_slot (&_dbus_gmain_connection_slot);
00564 if (_dbus_gmain_connection_slot < 0)
00565 goto nomem;
00566
00567 if (context == NULL)
00568 context = g_main_context_default ();
00569
00570 cs = NULL;
00571
00572 old_setup = dbus_connection_get_data (connection, _dbus_gmain_connection_slot);
00573 if (old_setup != NULL)
00574 {
00575 if (old_setup->context == context)
00576 return;
00577
00578 cs = connection_setup_new_from_old (context, old_setup);
00579
00580
00581 dbus_connection_set_data (connection, _dbus_gmain_connection_slot, NULL, NULL);
00582 old_setup = NULL;
00583 }
00584
00585 if (cs == NULL)
00586 cs = connection_setup_new (context, connection);
00587
00588 if (!dbus_connection_set_data (connection, _dbus_gmain_connection_slot, cs,
00589 (DBusFreeFunction)connection_setup_free))
00590 goto nomem;
00591
00592 if (!dbus_connection_set_watch_functions (connection,
00593 add_watch,
00594 remove_watch,
00595 watch_toggled,
00596 cs, NULL))
00597 goto nomem;
00598
00599 if (!dbus_connection_set_timeout_functions (connection,
00600 add_timeout,
00601 remove_timeout,
00602 timeout_toggled,
00603 cs, NULL))
00604 goto nomem;
00605
00606 dbus_connection_set_wakeup_main_function (connection,
00607 wakeup_main,
00608 cs, NULL);
00609
00610 return;
00611
00612 nomem:
00613 g_error ("Not enough memory to set up DBusConnection for use with GLib");
00614 }
00615
00630 void
00631 dbus_server_setup_with_g_main (DBusServer *server,
00632 GMainContext *context)
00633 {
00634 ConnectionSetup *old_setup;
00635 ConnectionSetup *cs;
00636
00637
00638
00639
00640 dbus_server_allocate_data_slot (&server_slot);
00641 if (server_slot < 0)
00642 goto nomem;
00643
00644 if (context == NULL)
00645 context = g_main_context_default ();
00646
00647 cs = NULL;
00648
00649 old_setup = dbus_server_get_data (server, server_slot);
00650 if (old_setup != NULL)
00651 {
00652 if (old_setup->context == context)
00653 return;
00654
00655 cs = connection_setup_new_from_old (context, old_setup);
00656
00657
00658 dbus_server_set_data (server, server_slot, NULL, NULL);
00659 old_setup = NULL;
00660 }
00661
00662 if (cs == NULL)
00663 cs = connection_setup_new (context, NULL);
00664
00665 if (!dbus_server_set_data (server, server_slot, cs,
00666 (DBusFreeFunction)connection_setup_free))
00667 goto nomem;
00668
00669 if (!dbus_server_set_watch_functions (server,
00670 add_watch,
00671 remove_watch,
00672 watch_toggled,
00673 cs, NULL))
00674 goto nomem;
00675
00676 if (!dbus_server_set_timeout_functions (server,
00677 add_timeout,
00678 remove_timeout,
00679 timeout_toggled,
00680 cs, NULL))
00681 goto nomem;
00682
00683 return;
00684
00685 nomem:
00686 g_error ("Not enough memory to set up DBusServer for use with GLib");
00687 }
00688
00701 DBusGConnection*
00702 dbus_g_connection_open (const gchar *address,
00703 GError **error)
00704 {
00705 DBusConnection *connection;
00706 DBusError derror;
00707
00708 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
00709
00710 _dbus_g_value_types_init ();
00711
00712 dbus_error_init (&derror);
00713
00714 connection = dbus_connection_open (address, &derror);
00715 if (connection == NULL)
00716 {
00717 dbus_set_g_error (error, &derror);
00718 dbus_error_free (&derror);
00719 return NULL;
00720 }
00721
00722
00723 dbus_connection_setup_with_g_main (connection, NULL);
00724
00725 return DBUS_G_CONNECTION_FROM_CONNECTION (connection);
00726 }
00727
00741 DBusGConnection*
00742 dbus_g_bus_get (DBusBusType type,
00743 GError **error)
00744 {
00745 DBusConnection *connection;
00746 DBusError derror;
00747
00748 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
00749
00750 _dbus_g_value_types_init ();
00751
00752 dbus_error_init (&derror);
00753
00754 connection = dbus_bus_get (type, &derror);
00755 if (connection == NULL)
00756 {
00757 dbus_set_g_error (error, &derror);
00758 dbus_error_free (&derror);
00759 return NULL;
00760 }
00761
00762
00763 dbus_connection_setup_with_g_main (connection, NULL);
00764
00765 return DBUS_G_CONNECTION_FROM_CONNECTION (connection);
00766 }
00767
00769
00770 #ifdef DBUS_BUILD_TESTS
00771
00777 gboolean
00778 _dbus_gmain_test (const char *test_data_dir)
00779 {
00780 GType type;
00781 GType rectype;
00782
00783 g_type_init ();
00784 _dbus_g_value_types_init ();
00785
00786 rectype = dbus_g_type_get_collection ("GArray", G_TYPE_UINT);
00787 g_assert (rectype != G_TYPE_INVALID);
00788 g_assert (!strcmp (g_type_name (rectype), "GArray_guint_"));
00789
00790 type = _dbus_gtype_from_signature ("au", TRUE);
00791 g_assert (type == rectype);
00792
00793 rectype = dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING);
00794 g_assert (rectype != G_TYPE_INVALID);
00795 g_assert (!strcmp (g_type_name (rectype), "GHashTable_gchararray+gchararray_"));
00796
00797 type = _dbus_gtype_from_signature ("a{ss}", TRUE);
00798 g_assert (type == rectype);
00799
00800 type = _dbus_gtype_from_signature ("o", FALSE);
00801 g_assert (type == DBUS_TYPE_G_OBJECT_PATH);
00802 type = _dbus_gtype_from_signature ("o", TRUE);
00803 g_assert (type == DBUS_TYPE_G_OBJECT_PATH);
00804
00805 type = _dbus_gtype_from_signature ("g", TRUE);
00806 g_assert (type == DBUS_TYPE_G_SIGNATURE);
00807
00808 return TRUE;
00809 }
00810
00811 #endif