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-glib.h"
00026 #include "dbus-gtest.h"
00027
00028 #include <libintl.h>
00029 #define _(x) dgettext (GETTEXT_PACKAGE, x)
00030 #define N_(x) x
00031
00054 typedef struct DBusGSource DBusGSource;
00055
00059 struct DBusGSource
00060 {
00061 GSource source;
00063 GList *watch_fds;
00065 GMainContext *context;
00067 void *connection_or_server;
00068 };
00069
00070 typedef struct
00071 {
00072 int refcount;
00073
00074 GPollFD poll_fd;
00075 DBusWatch *watch;
00076
00077 unsigned int removed : 1;
00078 } WatchFD;
00079
00080 static WatchFD *
00081 watch_fd_new (void)
00082 {
00083 WatchFD *watch_fd;
00084
00085 watch_fd = g_new0 (WatchFD, 1);
00086 watch_fd->refcount = 1;
00087
00088 return watch_fd;
00089 }
00090
00091 static WatchFD *
00092 watch_fd_ref (WatchFD *watch_fd)
00093 {
00094 watch_fd->refcount += 1;
00095
00096 return watch_fd;
00097 }
00098
00099 static void
00100 watch_fd_unref (WatchFD *watch_fd)
00101 {
00102 watch_fd->refcount -= 1;
00103
00104 if (watch_fd->refcount == 0)
00105 {
00106 g_assert (watch_fd->removed);
00107
00108 g_free (watch_fd);
00109 }
00110 }
00111
00112 static dbus_int32_t connection_slot = -1;
00113 static dbus_int32_t server_slot = -1;
00114
00115 static gboolean gsource_connection_prepare (GSource *source,
00116 gint *timeout);
00117 static gboolean gsource_connection_check (GSource *source);
00118 static gboolean gsource_connection_dispatch (GSource *source,
00119 GSourceFunc callback,
00120 gpointer user_data);
00121 static gboolean gsource_server_prepare (GSource *source,
00122 gint *timeout);
00123 static gboolean gsource_server_check (GSource *source);
00124 static gboolean gsource_server_dispatch (GSource *source,
00125 GSourceFunc callback,
00126 gpointer user_data);
00127
00128 static GSourceFuncs dbus_connection_funcs = {
00129 gsource_connection_prepare,
00130 gsource_connection_check,
00131 gsource_connection_dispatch,
00132 NULL
00133 };
00134
00135 static GSourceFuncs dbus_server_funcs = {
00136 gsource_server_prepare,
00137 gsource_server_check,
00138 gsource_server_dispatch,
00139 NULL
00140 };
00141
00142 static gboolean
00143 gsource_connection_prepare (GSource *source,
00144 gint *timeout)
00145 {
00146 DBusConnection *connection = ((DBusGSource *)source)->connection_or_server;
00147
00148 *timeout = -1;
00149
00150 return (dbus_connection_get_dispatch_status (connection) == DBUS_DISPATCH_DATA_REMAINS);
00151 }
00152
00153 static gboolean
00154 gsource_server_prepare (GSource *source,
00155 gint *timeout)
00156 {
00157 *timeout = -1;
00158
00159 return FALSE;
00160 }
00161
00162 static gboolean
00163 dbus_gsource_check (GSource *source)
00164 {
00165 DBusGSource *dbus_source = (DBusGSource *)source;
00166 GList *list;
00167
00168 list = dbus_source->watch_fds;
00169
00170 while (list)
00171 {
00172 WatchFD *watch_fd = list->data;
00173
00174 if (watch_fd->poll_fd.revents != 0)
00175 return TRUE;
00176
00177 list = list->next;
00178 }
00179
00180 return FALSE;
00181 }
00182
00183 static gboolean
00184 gsource_connection_check (GSource *source)
00185 {
00186 return dbus_gsource_check (source);
00187 }
00188
00189 static gboolean
00190 gsource_server_check (GSource *source)
00191 {
00192 return dbus_gsource_check (source);
00193 }
00194
00195 static gboolean
00196 dbus_gsource_dispatch (GSource *source,
00197 GSourceFunc callback,
00198 gpointer user_data,
00199 dbus_bool_t is_server)
00200 {
00201 DBusGSource *dbus_source = (DBusGSource *)source;
00202 GList *copy, *list;
00203
00204
00205 copy = g_list_copy (dbus_source->watch_fds);
00206 g_list_foreach (copy, (GFunc)watch_fd_ref, NULL);
00207
00208 list = copy;
00209 while (list)
00210 {
00211 WatchFD *watch_fd = list->data;
00212
00213 if (!watch_fd->removed && watch_fd->poll_fd.revents != 0)
00214 {
00215 guint condition = 0;
00216
00217 if (watch_fd->poll_fd.revents & G_IO_IN)
00218 condition |= DBUS_WATCH_READABLE;
00219 if (watch_fd->poll_fd.revents & G_IO_OUT)
00220 condition |= DBUS_WATCH_WRITABLE;
00221 if (watch_fd->poll_fd.revents & G_IO_ERR)
00222 condition |= DBUS_WATCH_ERROR;
00223 if (watch_fd->poll_fd.revents & G_IO_HUP)
00224 condition |= DBUS_WATCH_HANGUP;
00225
00226 dbus_watch_handle (watch_fd->watch, condition);
00227 }
00228
00229 list = list->next;
00230 }
00231
00232 g_list_foreach (copy, (GFunc)watch_fd_unref, NULL);
00233 g_list_free (copy);
00234
00235 return TRUE;
00236 }
00237
00238 static gboolean
00239 gsource_connection_dispatch (GSource *source,
00240 GSourceFunc callback,
00241 gpointer user_data)
00242 {
00243 DBusGSource *dbus_source = (DBusGSource *)source;
00244 DBusConnection *connection = dbus_source->connection_or_server;
00245
00246 dbus_connection_ref (connection);
00247
00248 dbus_gsource_dispatch (source, callback, user_data,
00249 FALSE);
00250
00251
00252 while (dbus_connection_dispatch (connection) == DBUS_DISPATCH_DATA_REMAINS)
00253 ;
00254
00255 dbus_connection_unref (connection);
00256
00257 return TRUE;
00258 }
00259
00260 static gboolean
00261 gsource_server_dispatch (GSource *source,
00262 GSourceFunc callback,
00263 gpointer user_data)
00264 {
00265 DBusGSource *dbus_source = (DBusGSource *)source;
00266 DBusServer *server = dbus_source->connection_or_server;
00267
00268 dbus_server_ref (server);
00269
00270 dbus_gsource_dispatch (source, callback, user_data,
00271 TRUE);
00272
00273 dbus_server_unref (server);
00274
00275 return TRUE;
00276 }
00277
00278 static dbus_bool_t
00279 add_watch (DBusWatch *watch,
00280 gpointer data)
00281 {
00282 WatchFD *watch_fd;
00283 DBusGSource *dbus_source;
00284 guint flags;
00285
00286 if (!dbus_watch_get_enabled (watch))
00287 return TRUE;
00288
00289 dbus_source = data;
00290
00291 watch_fd = watch_fd_new ();
00292 watch_fd->poll_fd.fd = dbus_watch_get_fd (watch);
00293 watch_fd->poll_fd.events = 0;
00294 flags = dbus_watch_get_flags (watch);
00295 dbus_watch_set_data (watch, watch_fd, (DBusFreeFunction)watch_fd_unref);
00296
00297 if (flags & DBUS_WATCH_READABLE)
00298 watch_fd->poll_fd.events |= G_IO_IN;
00299 if (flags & DBUS_WATCH_WRITABLE)
00300 watch_fd->poll_fd.events |= G_IO_OUT;
00301 watch_fd->poll_fd.events |= G_IO_ERR | G_IO_HUP;
00302
00303 watch_fd->watch = watch;
00304
00305 g_source_add_poll ((GSource *)dbus_source, &watch_fd->poll_fd);
00306
00307 dbus_source->watch_fds = g_list_prepend (dbus_source->watch_fds, watch_fd);
00308
00309 return TRUE;
00310 }
00311
00312 static void
00313 remove_watch (DBusWatch *watch,
00314 gpointer data)
00315 {
00316 DBusGSource *dbus_source = data;
00317 WatchFD *watch_fd;
00318
00319 watch_fd = dbus_watch_get_data (watch);
00320 if (watch_fd == NULL)
00321 return;
00322
00323 watch_fd->removed = TRUE;
00324 watch_fd->watch = NULL;
00325
00326 dbus_source->watch_fds = g_list_remove (dbus_source->watch_fds, watch_fd);
00327
00328 g_source_remove_poll ((GSource *)dbus_source, &watch_fd->poll_fd);
00329
00330 dbus_watch_set_data (watch, NULL, NULL);
00331
00332
00333 }
00334
00335 static void
00336 watch_toggled (DBusWatch *watch,
00337 void *data)
00338 {
00339
00340
00341
00342 if (dbus_watch_get_enabled (watch))
00343 add_watch (watch, data);
00344 else
00345 remove_watch (watch, data);
00346 }
00347
00348 static gboolean
00349 timeout_handler (gpointer data)
00350 {
00351 DBusTimeout *timeout = data;
00352
00353 dbus_timeout_handle (timeout);
00354
00355 return TRUE;
00356 }
00357
00358 static dbus_bool_t
00359 add_timeout (DBusTimeout *timeout,
00360 void *data)
00361 {
00362 DBusGSource *dbus_source = data;
00363 GSource *source;
00364
00365 if (!dbus_timeout_get_enabled (timeout))
00366 return TRUE;
00367
00368 source = g_timeout_source_new (dbus_timeout_get_interval (timeout));
00369 g_source_set_callback (source, timeout_handler, timeout, NULL);
00370 g_source_attach (source, dbus_source->context);
00371
00372 dbus_timeout_set_data (timeout, GUINT_TO_POINTER (g_source_get_id (source)),
00373 NULL);
00374
00375 return TRUE;
00376 }
00377
00378 static void
00379 remove_timeout (DBusTimeout *timeout,
00380 void *data)
00381 {
00382 guint timeout_tag;
00383
00384 timeout_tag = GPOINTER_TO_UINT (dbus_timeout_get_data (timeout));
00385
00386 if (timeout_tag != 0)
00387 g_source_remove (timeout_tag);
00388 }
00389
00390 static void
00391 timeout_toggled (DBusTimeout *timeout,
00392 void *data)
00393 {
00394
00395
00396
00397 if (dbus_timeout_get_enabled (timeout))
00398 add_timeout (timeout, data);
00399 else
00400 remove_timeout (timeout, data);
00401 }
00402
00403
00404 static void
00405 free_source (GSource *source)
00406 {
00407 g_source_destroy (source);
00408 }
00409
00410 static void
00411 wakeup_main (void *data)
00412 {
00413 DBusGSource *dbus_source = data;
00414
00415 g_main_context_wakeup (dbus_source->context);
00416 }
00417
00418
00420
00425 static GSource*
00426 create_source (void *connection_or_server,
00427 GSourceFuncs *funcs,
00428 GMainContext *context)
00429 {
00430 GSource *source;
00431 DBusGSource *dbus_source;
00432
00433 source = g_source_new (funcs, sizeof (DBusGSource));
00434
00435 dbus_source = (DBusGSource *)source;
00436 dbus_source->connection_or_server = connection_or_server;
00437 dbus_source->context = context;
00438
00439 return source;
00440 }
00441
00456 void
00457 dbus_connection_setup_with_g_main (DBusConnection *connection,
00458 GMainContext *context)
00459 {
00460 GSource *source;
00461
00462
00463
00464
00465 dbus_connection_allocate_data_slot (&connection_slot);
00466 if (connection_slot < 0)
00467 goto nomem;
00468
00469
00470 if (context == NULL)
00471 context = g_main_context_default ();
00472
00473 source = dbus_connection_get_data (connection, connection_slot);
00474 if (source != NULL)
00475 {
00476 if (source->context == context)
00477 return;
00478
00479
00480 dbus_connection_set_data (connection, connection_slot, NULL, NULL);
00481 source = NULL;
00482 }
00483
00484 source = create_source (connection, &dbus_connection_funcs, context);
00485
00486 if (!dbus_connection_set_watch_functions (connection,
00487 add_watch,
00488 remove_watch,
00489 watch_toggled,
00490 source, NULL))
00491 goto nomem;
00492
00493 if (!dbus_connection_set_timeout_functions (connection,
00494 add_timeout,
00495 remove_timeout,
00496 timeout_toggled,
00497 source, NULL))
00498 goto nomem;
00499
00500 dbus_connection_set_wakeup_main_function (connection,
00501 wakeup_main,
00502 source, NULL);
00503
00504 g_source_attach (source, context);
00505
00506 if (!dbus_connection_set_data (connection, connection_slot, source,
00507 (DBusFreeFunction)free_source))
00508 goto nomem;
00509
00510 return;
00511
00512 nomem:
00513 g_error ("Not enough memory to set up DBusConnection for use with GLib");
00514 }
00515
00529 void
00530 dbus_server_setup_with_g_main (DBusServer *server,
00531 GMainContext *context)
00532 {
00533 GSource *source;
00534
00535 dbus_server_allocate_data_slot (&server_slot);
00536 if (server_slot < 0)
00537 goto nomem;
00538
00539
00540 if (context == NULL)
00541 context = g_main_context_default ();
00542
00543 source = dbus_server_get_data (server, server_slot);
00544 if (source != NULL)
00545 {
00546 if (source->context == context)
00547 return;
00548
00549
00550 dbus_server_set_data (server, server_slot, NULL, NULL);
00551 source = NULL;
00552 }
00553
00554 source = create_source (server, &dbus_server_funcs, context);
00555
00556 dbus_server_set_watch_functions (server,
00557 add_watch,
00558 remove_watch,
00559 watch_toggled,
00560 source, NULL);
00561
00562 dbus_server_set_timeout_functions (server,
00563 add_timeout,
00564 remove_timeout,
00565 timeout_toggled,
00566 NULL, NULL);
00567
00568 g_source_attach (source, context);
00569
00570 if (!dbus_server_set_data (server, server_slot, source,
00571 (DBusFreeFunction)free_source))
00572 goto nomem;
00573
00574 return;
00575
00576 nomem:
00577 g_error ("Not enough memory to set up DBusServer for use with GLib");
00578 }
00579
00588 DBusConnection*
00589 dbus_bus_get_with_g_main (DBusBusType type,
00590 GError **error)
00591 {
00592 DBusConnection *connection;
00593 DBusError derror;
00594
00595 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
00596
00597 dbus_error_init (&derror);
00598
00599 connection = dbus_bus_get (type, &derror);
00600 if (connection == NULL)
00601 {
00602 dbus_set_g_error (error, &derror);
00603 dbus_error_free (&derror);
00604 }
00605 else
00606 {
00607
00608 dbus_connection_setup_with_g_main (connection, NULL);
00609 }
00610
00611 return connection;
00612 }
00613
00620 GQuark
00621 dbus_g_error_quark (void)
00622 {
00623 static GQuark quark = 0;
00624 if (quark == 0)
00625 quark = g_quark_from_static_string ("g-exec-error-quark");
00626 return quark;
00627 }
00628
00629
00638 void
00639 dbus_set_g_error (GError **gerror,
00640 DBusError *derror)
00641 {
00642 g_return_if_fail (derror != NULL);
00643 g_return_if_fail (dbus_error_is_set (derror));
00644
00645 g_set_error (gerror, DBUS_GERROR,
00646 DBUS_GERROR_FAILED,
00647 _("D-BUS error %s: %s"),
00648 derror->name, derror->message);
00649 }
00650
00656 GType
00657 dbus_connection_get_g_type (void)
00658 {
00659 static GType our_type = 0;
00660
00661 if (our_type == 0)
00662 our_type = g_boxed_type_register_static ("DBusConnection",
00663 (GBoxedCopyFunc) dbus_connection_ref,
00664 (GBoxedFreeFunc) dbus_connection_unref);
00665
00666 return our_type;
00667 }
00668
00674 GType
00675 dbus_message_get_g_type (void)
00676 {
00677 static GType our_type = 0;
00678
00679 if (our_type == 0)
00680 our_type = g_boxed_type_register_static ("DBusMessage",
00681 (GBoxedCopyFunc) dbus_message_ref,
00682 (GBoxedFreeFunc) dbus_message_unref);
00683
00684 return our_type;
00685 }
00686
00687
00689
00690 #ifdef DBUS_BUILD_TESTS
00691
00697 dbus_bool_t
00698 _dbus_gmain_test (const char *test_data_dir)
00699 {
00700
00701 return TRUE;
00702 }
00703
00704 #endif