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