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