00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <config.h>
00025 #include <dbus/dbus-glib.h>
00026 #include <dbus/dbus-glib-lowlevel.h>
00027 #include "dbus-gtest.h"
00028 #include "dbus-gutils.h"
00029
00030 #include <libintl.h>
00031 #define _(x) dgettext (GETTEXT_PACKAGE, x)
00032 #define N_(x) x
00033
00056 typedef struct DBusGSource DBusGSource;
00057
00061 struct DBusGSource
00062 {
00063 GSource source;
00065 GList *watch_fds;
00067 GMainContext *context;
00069 void *connection_or_server;
00070 };
00071
00076 typedef struct
00077 {
00078 int refcount;
00080 GPollFD poll_fd;
00081 DBusWatch *watch;
00083 unsigned int removed : 1;
00084 } WatchFD;
00085
00086 static WatchFD *
00087 watch_fd_new (void)
00088 {
00089 WatchFD *watch_fd;
00090
00091 watch_fd = g_new0 (WatchFD, 1);
00092 watch_fd->refcount = 1;
00093
00094 return watch_fd;
00095 }
00096
00097 static WatchFD *
00098 watch_fd_ref (WatchFD *watch_fd)
00099 {
00100 watch_fd->refcount += 1;
00101
00102 return watch_fd;
00103 }
00104
00105 static void
00106 watch_fd_unref (WatchFD *watch_fd)
00107 {
00108 watch_fd->refcount -= 1;
00109
00110 if (watch_fd->refcount == 0)
00111 {
00112 g_assert (watch_fd->removed);
00113
00114 g_free (watch_fd);
00115 }
00116 }
00117
00118 static dbus_int32_t connection_slot = -1;
00119 static dbus_int32_t server_slot = -1;
00120
00121 static gboolean gsource_connection_prepare (GSource *source,
00122 gint *timeout);
00123 static gboolean gsource_connection_check (GSource *source);
00124 static gboolean gsource_connection_dispatch (GSource *source,
00125 GSourceFunc callback,
00126 gpointer user_data);
00127 static gboolean gsource_server_prepare (GSource *source,
00128 gint *timeout);
00129 static gboolean gsource_server_check (GSource *source);
00130 static gboolean gsource_server_dispatch (GSource *source,
00131 GSourceFunc callback,
00132 gpointer user_data);
00133
00134 static GSourceFuncs dbus_connection_funcs = {
00135 gsource_connection_prepare,
00136 gsource_connection_check,
00137 gsource_connection_dispatch,
00138 NULL
00139 };
00140
00141 static GSourceFuncs dbus_server_funcs = {
00142 gsource_server_prepare,
00143 gsource_server_check,
00144 gsource_server_dispatch,
00145 NULL
00146 };
00147
00148 static gboolean
00149 gsource_connection_prepare (GSource *source,
00150 gint *timeout)
00151 {
00152 DBusConnection *connection = ((DBusGSource *)source)->connection_or_server;
00153
00154 *timeout = -1;
00155
00156 return (dbus_connection_get_dispatch_status (connection) == DBUS_DISPATCH_DATA_REMAINS);
00157 }
00158
00159 static gboolean
00160 gsource_server_prepare (GSource *source,
00161 gint *timeout)
00162 {
00163 *timeout = -1;
00164
00165 return FALSE;
00166 }
00167
00168 static gboolean
00169 dbus_gsource_check (GSource *source)
00170 {
00171 DBusGSource *dbus_source = (DBusGSource *)source;
00172 GList *list;
00173
00174 list = dbus_source->watch_fds;
00175
00176 while (list)
00177 {
00178 WatchFD *watch_fd = list->data;
00179
00180 if (watch_fd->poll_fd.revents != 0)
00181 return TRUE;
00182
00183 list = list->next;
00184 }
00185
00186 return FALSE;
00187 }
00188
00189 static gboolean
00190 gsource_connection_check (GSource *source)
00191 {
00192 return dbus_gsource_check (source);
00193 }
00194
00195 static gboolean
00196 gsource_server_check (GSource *source)
00197 {
00198 return dbus_gsource_check (source);
00199 }
00200
00201 static gboolean
00202 dbus_gsource_dispatch (GSource *source,
00203 GSourceFunc callback,
00204 gpointer user_data,
00205 dbus_bool_t is_server)
00206 {
00207 DBusGSource *dbus_source = (DBusGSource *)source;
00208 GList *copy, *list;
00209
00210
00211 copy = g_list_copy (dbus_source->watch_fds);
00212 g_list_foreach (copy, (GFunc)watch_fd_ref, NULL);
00213
00214 list = copy;
00215 while (list)
00216 {
00217 WatchFD *watch_fd = list->data;
00218
00219 if (!watch_fd->removed && watch_fd->poll_fd.revents != 0)
00220 {
00221 guint condition = 0;
00222
00223 if (watch_fd->poll_fd.revents & G_IO_IN)
00224 condition |= DBUS_WATCH_READABLE;
00225 if (watch_fd->poll_fd.revents & G_IO_OUT)
00226 condition |= DBUS_WATCH_WRITABLE;
00227 if (watch_fd->poll_fd.revents & G_IO_ERR)
00228 condition |= DBUS_WATCH_ERROR;
00229 if (watch_fd->poll_fd.revents & G_IO_HUP)
00230 condition |= DBUS_WATCH_HANGUP;
00231
00232 dbus_watch_handle (watch_fd->watch, condition);
00233 }
00234
00235 list = list->next;
00236 }
00237
00238 g_list_foreach (copy, (GFunc)watch_fd_unref, NULL);
00239 g_list_free (copy);
00240
00241 return TRUE;
00242 }
00243
00244 static gboolean
00245 gsource_connection_dispatch (GSource *source,
00246 GSourceFunc callback,
00247 gpointer user_data)
00248 {
00249 DBusGSource *dbus_source = (DBusGSource *)source;
00250 DBusConnection *connection = dbus_source->connection_or_server;
00251
00252 dbus_connection_ref (connection);
00253
00254 dbus_gsource_dispatch (source, callback, user_data,
00255 FALSE);
00256
00257
00258 while (dbus_connection_dispatch (connection) == DBUS_DISPATCH_DATA_REMAINS)
00259 ;
00260
00261 dbus_connection_unref (connection);
00262
00263 return TRUE;
00264 }
00265
00266 static gboolean
00267 gsource_server_dispatch (GSource *source,
00268 GSourceFunc callback,
00269 gpointer user_data)
00270 {
00271 DBusGSource *dbus_source = (DBusGSource *)source;
00272 DBusServer *server = dbus_source->connection_or_server;
00273
00274 dbus_server_ref (server);
00275
00276 dbus_gsource_dispatch (source, callback, user_data,
00277 TRUE);
00278
00279 dbus_server_unref (server);
00280
00281 return TRUE;
00282 }
00283
00284 static dbus_bool_t
00285 add_watch (DBusWatch *watch,
00286 gpointer data)
00287 {
00288 WatchFD *watch_fd;
00289 DBusGSource *dbus_source;
00290 guint flags;
00291
00292 if (!dbus_watch_get_enabled (watch))
00293 return TRUE;
00294
00295 dbus_source = data;
00296
00297 watch_fd = watch_fd_new ();
00298 watch_fd->poll_fd.fd = dbus_watch_get_fd (watch);
00299 watch_fd->poll_fd.events = 0;
00300 flags = dbus_watch_get_flags (watch);
00301 dbus_watch_set_data (watch, watch_fd, (DBusFreeFunction)watch_fd_unref);
00302
00303 if (flags & DBUS_WATCH_READABLE)
00304 watch_fd->poll_fd.events |= G_IO_IN;
00305 if (flags & DBUS_WATCH_WRITABLE)
00306 watch_fd->poll_fd.events |= G_IO_OUT;
00307 watch_fd->poll_fd.events |= G_IO_ERR | G_IO_HUP;
00308
00309 watch_fd->watch = watch;
00310
00311 g_source_add_poll ((GSource *)dbus_source, &watch_fd->poll_fd);
00312
00313 dbus_source->watch_fds = g_list_prepend (dbus_source->watch_fds, watch_fd);
00314
00315 return TRUE;
00316 }
00317
00318 static void
00319 remove_watch (DBusWatch *watch,
00320 gpointer data)
00321 {
00322 DBusGSource *dbus_source = data;
00323 WatchFD *watch_fd;
00324
00325 watch_fd = dbus_watch_get_data (watch);
00326 if (watch_fd == NULL)
00327 return;
00328
00329 watch_fd->removed = TRUE;
00330 watch_fd->watch = NULL;
00331
00332 dbus_source->watch_fds = g_list_remove (dbus_source->watch_fds, watch_fd);
00333
00334 g_source_remove_poll ((GSource *)dbus_source, &watch_fd->poll_fd);
00335
00336 dbus_watch_set_data (watch, NULL, NULL);
00337
00338
00339 }
00340
00341 static void
00342 watch_toggled (DBusWatch *watch,
00343 void *data)
00344 {
00345
00346
00347
00348 if (dbus_watch_get_enabled (watch))
00349 add_watch (watch, data);
00350 else
00351 remove_watch (watch, data);
00352 }
00353
00354 static gboolean
00355 timeout_handler (gpointer data)
00356 {
00357 DBusTimeout *timeout = data;
00358
00359 dbus_timeout_handle (timeout);
00360
00361 return TRUE;
00362 }
00363
00364 static dbus_bool_t
00365 add_timeout (DBusTimeout *timeout,
00366 void *data)
00367 {
00368 DBusGSource *dbus_source = data;
00369 GSource *source;
00370
00371 if (!dbus_timeout_get_enabled (timeout))
00372 return TRUE;
00373
00374 source = g_timeout_source_new (dbus_timeout_get_interval (timeout));
00375 g_source_set_callback (source, timeout_handler, timeout, NULL);
00376 g_source_attach (source, dbus_source->context);
00377
00378 dbus_timeout_set_data (timeout, GUINT_TO_POINTER (g_source_get_id (source)),
00379 NULL);
00380
00381 return TRUE;
00382 }
00383
00384 static void
00385 remove_timeout (DBusTimeout *timeout,
00386 void *data)
00387 {
00388 guint timeout_tag;
00389
00390 timeout_tag = GPOINTER_TO_UINT (dbus_timeout_get_data (timeout));
00391
00392 if (timeout_tag != 0)
00393 g_source_remove (timeout_tag);
00394 }
00395
00396 static void
00397 timeout_toggled (DBusTimeout *timeout,
00398 void *data)
00399 {
00400
00401
00402
00403 if (dbus_timeout_get_enabled (timeout))
00404 add_timeout (timeout, data);
00405 else
00406 remove_timeout (timeout, data);
00407 }
00408
00409
00410 static void
00411 free_source (GSource *source)
00412 {
00413 g_source_destroy (source);
00414 }
00415
00416 static void
00417 wakeup_main (void *data)
00418 {
00419 DBusGSource *dbus_source = data;
00420
00421 g_main_context_wakeup (dbus_source->context);
00422 }
00423
00424
00426
00431 static GSource*
00432 create_source (void *connection_or_server,
00433 GSourceFuncs *funcs,
00434 GMainContext *context)
00435 {
00436 GSource *source;
00437 DBusGSource *dbus_source;
00438
00439 source = g_source_new (funcs, sizeof (DBusGSource));
00440
00441 dbus_source = (DBusGSource *)source;
00442 dbus_source->connection_or_server = connection_or_server;
00443 dbus_source->context = context;
00444
00445 return source;
00446 }
00447
00462 void
00463 dbus_connection_setup_with_g_main (DBusConnection *connection,
00464 GMainContext *context)
00465 {
00466 GSource *source;
00467
00468
00469
00470
00471 dbus_connection_allocate_data_slot (&connection_slot);
00472 if (connection_slot < 0)
00473 goto nomem;
00474
00475
00476 if (context == NULL)
00477 context = g_main_context_default ();
00478
00479 source = dbus_connection_get_data (connection, connection_slot);
00480 if (source != NULL)
00481 {
00482 if (source->context == context)
00483 return;
00484
00485
00486 dbus_connection_set_data (connection, connection_slot, NULL, NULL);
00487 source = NULL;
00488 }
00489
00490 source = create_source (connection, &dbus_connection_funcs, context);
00491
00492 if (!dbus_connection_set_watch_functions (connection,
00493 add_watch,
00494 remove_watch,
00495 watch_toggled,
00496 source, NULL))
00497 goto nomem;
00498
00499 if (!dbus_connection_set_timeout_functions (connection,
00500 add_timeout,
00501 remove_timeout,
00502 timeout_toggled,
00503 source, NULL))
00504 goto nomem;
00505
00506 dbus_connection_set_wakeup_main_function (connection,
00507 wakeup_main,
00508 source, NULL);
00509
00510 g_source_attach (source, context);
00511
00512 if (!dbus_connection_set_data (connection, connection_slot, source,
00513 (DBusFreeFunction)free_source))
00514 goto nomem;
00515
00516 return;
00517
00518 nomem:
00519 g_error ("Not enough memory to set up DBusConnection for use with GLib");
00520 }
00521
00535 void
00536 dbus_server_setup_with_g_main (DBusServer *server,
00537 GMainContext *context)
00538 {
00539 GSource *source;
00540
00541 dbus_server_allocate_data_slot (&server_slot);
00542 if (server_slot < 0)
00543 goto nomem;
00544
00545
00546 if (context == NULL)
00547 context = g_main_context_default ();
00548
00549 source = dbus_server_get_data (server, server_slot);
00550 if (source != NULL)
00551 {
00552 if (source->context == context)
00553 return;
00554
00555
00556 dbus_server_set_data (server, server_slot, NULL, NULL);
00557 source = NULL;
00558 }
00559
00560 source = create_source (server, &dbus_server_funcs, context);
00561
00562 dbus_server_set_watch_functions (server,
00563 add_watch,
00564 remove_watch,
00565 watch_toggled,
00566 source, NULL);
00567
00568 dbus_server_set_timeout_functions (server,
00569 add_timeout,
00570 remove_timeout,
00571 timeout_toggled,
00572 NULL, NULL);
00573
00574 g_source_attach (source, context);
00575
00576 if (!dbus_server_set_data (server, server_slot, source,
00577 (DBusFreeFunction)free_source))
00578 goto nomem;
00579
00580 return;
00581
00582 nomem:
00583 g_error ("Not enough memory to set up DBusServer for use with GLib");
00584 }
00585
00597 DBusGConnection*
00598 dbus_g_bus_get (DBusBusType type,
00599 GError **error)
00600 {
00601 DBusConnection *connection;
00602 DBusError derror;
00603
00604 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
00605
00606 dbus_error_init (&derror);
00607
00608 connection = dbus_bus_get (type, &derror);
00609 if (connection == NULL)
00610 {
00611 dbus_set_g_error (error, &derror);
00612 dbus_error_free (&derror);
00613 }
00614 else
00615 {
00616
00617 dbus_connection_setup_with_g_main (connection, NULL);
00618 }
00619
00620 return DBUS_G_CONNECTION_FROM_CONNECTION (connection);
00621 }
00622
00629 GQuark
00630 dbus_g_error_quark (void)
00631 {
00632 static GQuark quark = 0;
00633 if (quark == 0)
00634 quark = g_quark_from_static_string ("g-exec-error-quark");
00635 return quark;
00636 }
00637
00638
00647 void
00648 dbus_set_g_error (GError **gerror,
00649 DBusError *derror)
00650 {
00651 g_return_if_fail (derror != NULL);
00652 g_return_if_fail (dbus_error_is_set (derror));
00653
00654 g_set_error (gerror, DBUS_GERROR,
00655 DBUS_GERROR_FAILED,
00656 _("D-BUS error %s: %s"),
00657 derror->name, derror->message);
00658 }
00659
00665 GType
00666 dbus_connection_get_g_type (void)
00667 {
00668 static GType our_type = 0;
00669
00670 if (our_type == 0)
00671 our_type = g_boxed_type_register_static ("DBusConnection",
00672 (GBoxedCopyFunc) dbus_connection_ref,
00673 (GBoxedFreeFunc) dbus_connection_unref);
00674
00675 return our_type;
00676 }
00677
00683 GType
00684 dbus_message_get_g_type (void)
00685 {
00686 static GType our_type = 0;
00687
00688 if (our_type == 0)
00689 our_type = g_boxed_type_register_static ("DBusMessage",
00690 (GBoxedCopyFunc) dbus_message_ref,
00691 (GBoxedFreeFunc) dbus_message_unref);
00692
00693 return our_type;
00694 }
00695
00696 static DBusGConnection*
00697 dbus_g_connection_ref (DBusGConnection *gconnection)
00698 {
00699 DBusConnection *c;
00700
00701 c = DBUS_CONNECTION_FROM_G_CONNECTION (gconnection);
00702 dbus_connection_ref (c);
00703 return gconnection;
00704 }
00705
00706 static void
00707 dbus_g_connection_unref (DBusGConnection *gconnection)
00708 {
00709 DBusConnection *c;
00710
00711 c = DBUS_CONNECTION_FROM_G_CONNECTION (gconnection);
00712 dbus_connection_unref (c);
00713 }
00714
00715
00716 static DBusGMessage*
00717 dbus_g_message_ref (DBusGMessage *gmessage)
00718 {
00719 DBusMessage *c;
00720
00721 c = DBUS_MESSAGE_FROM_G_MESSAGE (gmessage);
00722 dbus_message_ref (c);
00723 return gmessage;
00724 }
00725
00726 static void
00727 dbus_g_message_unref (DBusGMessage *gmessage)
00728 {
00729 DBusMessage *c;
00730
00731 c = DBUS_MESSAGE_FROM_G_MESSAGE (gmessage);
00732 dbus_message_unref (c);
00733 }
00734
00740 GType
00741 dbus_g_connection_get_g_type (void)
00742 {
00743 static GType our_type = 0;
00744
00745 if (our_type == 0)
00746 our_type = g_boxed_type_register_static ("DBusGConnection",
00747 (GBoxedCopyFunc) dbus_g_connection_ref,
00748 (GBoxedFreeFunc) dbus_g_connection_unref);
00749
00750 return our_type;
00751 }
00752
00758 GType
00759 dbus_g_message_get_g_type (void)
00760 {
00761 static GType our_type = 0;
00762
00763 if (our_type == 0)
00764 our_type = g_boxed_type_register_static ("DBusGMessage",
00765 (GBoxedCopyFunc) dbus_g_message_ref,
00766 (GBoxedFreeFunc) dbus_g_message_unref);
00767
00768 return our_type;
00769 }
00770
00777 DBusConnection*
00778 dbus_g_connection_get_connection (DBusGConnection *gconnection)
00779 {
00780 return DBUS_CONNECTION_FROM_G_CONNECTION (gconnection);
00781 }
00782
00789 DBusMessage*
00790 dbus_g_message_get_message (DBusGMessage *gmessage)
00791 {
00792 return DBUS_MESSAGE_FROM_G_MESSAGE (gmessage);
00793 }
00794
00796
00797 #ifdef DBUS_BUILD_TESTS
00798
00804 gboolean
00805 _dbus_gmain_test (const char *test_data_dir)
00806 {
00807
00808 return TRUE;
00809 }
00810
00811 #endif