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-internals.h"
00026 #include "dbus-watch.h"
00027 #include "dbus-list.h"
00028
00040 struct DBusWatch
00041 {
00042 int refcount;
00043 int fd;
00044 unsigned int flags;
00046 DBusWatchHandler handler;
00047 void *handler_data;
00048 DBusFreeFunction free_handler_data_function;
00050 void *data;
00051 DBusFreeFunction free_data_function;
00052 unsigned int enabled : 1;
00053 };
00054
00055 dbus_bool_t
00056 _dbus_watch_get_enabled (DBusWatch *watch)
00057 {
00058 return watch->enabled;
00059 }
00060
00073 DBusWatch*
00074 _dbus_watch_new (int fd,
00075 unsigned int flags,
00076 dbus_bool_t enabled,
00077 DBusWatchHandler handler,
00078 void *data,
00079 DBusFreeFunction free_data_function)
00080 {
00081 DBusWatch *watch;
00082
00083 #define VALID_WATCH_FLAGS (DBUS_WATCH_WRITABLE | DBUS_WATCH_READABLE)
00084
00085 _dbus_assert ((flags & VALID_WATCH_FLAGS) == flags);
00086
00087 watch = dbus_new0 (DBusWatch, 1);
00088 if (watch == NULL)
00089 return NULL;
00090
00091 watch->refcount = 1;
00092 watch->fd = fd;
00093 watch->flags = flags;
00094 watch->enabled = enabled;
00095
00096 watch->handler = handler;
00097 watch->handler_data = data;
00098 watch->free_handler_data_function = free_data_function;
00099
00100 return watch;
00101 }
00102
00109 DBusWatch *
00110 _dbus_watch_ref (DBusWatch *watch)
00111 {
00112 watch->refcount += 1;
00113
00114 return watch;
00115 }
00116
00123 void
00124 _dbus_watch_unref (DBusWatch *watch)
00125 {
00126 _dbus_assert (watch != NULL);
00127 _dbus_assert (watch->refcount > 0);
00128
00129 watch->refcount -= 1;
00130 if (watch->refcount == 0)
00131 {
00132 dbus_watch_set_data (watch, NULL, NULL);
00133
00134 if (watch->free_handler_data_function)
00135 (* watch->free_handler_data_function) (watch->handler_data);
00136
00137 dbus_free (watch);
00138 }
00139 }
00140
00151 void
00152 _dbus_watch_invalidate (DBusWatch *watch)
00153 {
00154 watch->fd = -1;
00155 watch->flags = 0;
00156 }
00157
00167 void
00168 _dbus_watch_sanitize_condition (DBusWatch *watch,
00169 unsigned int *condition)
00170 {
00171 if (!(watch->flags & DBUS_WATCH_READABLE))
00172 *condition &= ~DBUS_WATCH_READABLE;
00173 if (!(watch->flags & DBUS_WATCH_WRITABLE))
00174 *condition &= ~DBUS_WATCH_WRITABLE;
00175 }
00176
00177
00197 struct DBusWatchList
00198 {
00199 DBusList *watches;
00201 DBusAddWatchFunction add_watch_function;
00202 DBusRemoveWatchFunction remove_watch_function;
00203 DBusWatchToggledFunction watch_toggled_function;
00204 void *watch_data;
00205 DBusFreeFunction watch_free_data_function;
00206 };
00207
00214 DBusWatchList*
00215 _dbus_watch_list_new (void)
00216 {
00217 DBusWatchList *watch_list;
00218
00219 watch_list = dbus_new0 (DBusWatchList, 1);
00220 if (watch_list == NULL)
00221 return NULL;
00222
00223 return watch_list;
00224 }
00225
00231 void
00232 _dbus_watch_list_free (DBusWatchList *watch_list)
00233 {
00234
00235 _dbus_watch_list_set_functions (watch_list,
00236 NULL, NULL, NULL, NULL, NULL);
00237 _dbus_list_foreach (&watch_list->watches,
00238 (DBusForeachFunction) _dbus_watch_unref,
00239 NULL);
00240 _dbus_list_clear (&watch_list->watches);
00241
00242 dbus_free (watch_list);
00243 }
00244
00259 dbus_bool_t
00260 _dbus_watch_list_set_functions (DBusWatchList *watch_list,
00261 DBusAddWatchFunction add_function,
00262 DBusRemoveWatchFunction remove_function,
00263 DBusWatchToggledFunction toggled_function,
00264 void *data,
00265 DBusFreeFunction free_data_function)
00266 {
00267
00268 if (add_function != NULL)
00269 {
00270 DBusList *link;
00271
00272 link = _dbus_list_get_first_link (&watch_list->watches);
00273 while (link != NULL)
00274 {
00275 DBusList *next = _dbus_list_get_next_link (&watch_list->watches,
00276 link);
00277
00278 #ifdef DBUS_ENABLE_VERBOSE_MODE
00279 {
00280 const char *watch_type;
00281 int flags;
00282
00283 flags = dbus_watch_get_flags (link->data);
00284 if ((flags & DBUS_WATCH_READABLE) &&
00285 (flags & DBUS_WATCH_WRITABLE))
00286 watch_type = "readwrite";
00287 else if (flags & DBUS_WATCH_READABLE)
00288 watch_type = "read";
00289 else if (flags & DBUS_WATCH_WRITABLE)
00290 watch_type = "write";
00291 else
00292 watch_type = "not read or write";
00293
00294 _dbus_verbose ("Adding a %s watch on fd %d using newly-set add watch function\n",
00295 watch_type,
00296 dbus_watch_get_socket (link->data));
00297 }
00298 #endif
00299
00300 if (!(* add_function) (link->data, data))
00301 {
00302
00303 DBusList *link2;
00304
00305 link2 = _dbus_list_get_first_link (&watch_list->watches);
00306 while (link2 != link)
00307 {
00308 DBusList *next = _dbus_list_get_next_link (&watch_list->watches,
00309 link2);
00310
00311 _dbus_verbose ("Removing watch on fd %d using newly-set remove function because initial add failed\n",
00312 dbus_watch_get_socket (link2->data));
00313
00314 (* remove_function) (link2->data, data);
00315
00316 link2 = next;
00317 }
00318
00319 return FALSE;
00320 }
00321
00322 link = next;
00323 }
00324 }
00325
00326
00327
00328 if (watch_list->remove_watch_function != NULL)
00329 {
00330 _dbus_verbose ("Removing all pre-existing watches\n");
00331
00332 _dbus_list_foreach (&watch_list->watches,
00333 (DBusForeachFunction) watch_list->remove_watch_function,
00334 watch_list->watch_data);
00335 }
00336
00337 if (watch_list->watch_free_data_function != NULL)
00338 (* watch_list->watch_free_data_function) (watch_list->watch_data);
00339
00340 watch_list->add_watch_function = add_function;
00341 watch_list->remove_watch_function = remove_function;
00342 watch_list->watch_toggled_function = toggled_function;
00343 watch_list->watch_data = data;
00344 watch_list->watch_free_data_function = free_data_function;
00345
00346 return TRUE;
00347 }
00348
00357 dbus_bool_t
00358 _dbus_watch_list_add_watch (DBusWatchList *watch_list,
00359 DBusWatch *watch)
00360 {
00361 if (!_dbus_list_append (&watch_list->watches, watch))
00362 return FALSE;
00363
00364 _dbus_watch_ref (watch);
00365
00366 if (watch_list->add_watch_function != NULL)
00367 {
00368 _dbus_verbose ("Adding watch on fd %d\n",
00369 dbus_watch_get_socket (watch));
00370
00371 if (!(* watch_list->add_watch_function) (watch,
00372 watch_list->watch_data))
00373 {
00374 _dbus_list_remove_last (&watch_list->watches, watch);
00375 _dbus_watch_unref (watch);
00376 return FALSE;
00377 }
00378 }
00379
00380 return TRUE;
00381 }
00382
00390 void
00391 _dbus_watch_list_remove_watch (DBusWatchList *watch_list,
00392 DBusWatch *watch)
00393 {
00394 if (!_dbus_list_remove (&watch_list->watches, watch))
00395 _dbus_assert_not_reached ("Nonexistent watch was removed");
00396
00397 if (watch_list->remove_watch_function != NULL)
00398 {
00399 _dbus_verbose ("Removing watch on fd %d\n",
00400 dbus_watch_get_socket (watch));
00401
00402 (* watch_list->remove_watch_function) (watch,
00403 watch_list->watch_data);
00404 }
00405
00406 _dbus_watch_unref (watch);
00407 }
00408
00417 void
00418 _dbus_watch_list_toggle_watch (DBusWatchList *watch_list,
00419 DBusWatch *watch,
00420 dbus_bool_t enabled)
00421 {
00422 enabled = !!enabled;
00423
00424 if (enabled == watch->enabled)
00425 return;
00426
00427 watch->enabled = enabled;
00428
00429 if (watch_list->watch_toggled_function != NULL)
00430 {
00431 _dbus_verbose ("Toggling watch %p on fd %d to %d\n",
00432 watch, dbus_watch_get_socket (watch), watch->enabled);
00433
00434 (* watch_list->watch_toggled_function) (watch,
00435 watch_list->watch_data);
00436 }
00437 }
00438
00451 void
00452 _dbus_watch_set_handler (DBusWatch *watch,
00453 DBusWatchHandler handler,
00454 void *data,
00455 DBusFreeFunction free_data_function)
00456 {
00457 if (watch->free_handler_data_function)
00458 (* watch->free_handler_data_function) (watch->handler_data);
00459
00460 watch->handler = handler;
00461 watch->handler_data = data;
00462 watch->free_handler_data_function = free_data_function;
00463 }
00464
00496 int
00497 dbus_watch_get_fd (DBusWatch *watch)
00498 {
00499 return dbus_watch_get_unix_fd(watch);
00500 }
00501
00515 int
00516 dbus_watch_get_unix_fd (DBusWatch *watch)
00517 {
00518
00519
00520
00521
00522
00523 #ifdef DBUS_UNIX
00524 return watch->fd;
00525 #else
00526 return dbus_watch_get_socket( watch );
00527 #endif
00528 }
00529
00542 int
00543 dbus_watch_get_socket (DBusWatch *watch)
00544 {
00545 return watch->fd;
00546 }
00547
00561 unsigned int
00562 dbus_watch_get_flags (DBusWatch *watch)
00563 {
00564 _dbus_assert ((watch->flags & VALID_WATCH_FLAGS) == watch->flags);
00565
00566 return watch->flags;
00567 }
00568
00576 void*
00577 dbus_watch_get_data (DBusWatch *watch)
00578 {
00579 return watch->data;
00580 }
00581
00593 void
00594 dbus_watch_set_data (DBusWatch *watch,
00595 void *data,
00596 DBusFreeFunction free_data_function)
00597 {
00598 _dbus_verbose ("Setting watch fd %d data to data = %p function = %p from data = %p function = %p\n",
00599 dbus_watch_get_socket (watch),
00600 data, free_data_function, watch->data, watch->free_data_function);
00601
00602 if (watch->free_data_function != NULL)
00603 (* watch->free_data_function) (watch->data);
00604
00605 watch->data = data;
00606 watch->free_data_function = free_data_function;
00607 }
00608
00616 dbus_bool_t
00617 dbus_watch_get_enabled (DBusWatch *watch)
00618 {
00619 _dbus_assert (watch != NULL);
00620 return watch->enabled;
00621 }
00622
00623
00646 dbus_bool_t
00647 dbus_watch_handle (DBusWatch *watch,
00648 unsigned int flags)
00649 {
00650 #ifndef DBUS_DISABLE_CHECKS
00651 if (watch->fd < 0 || watch->flags == 0)
00652 {
00653 _dbus_warn_check_failed ("Watch is invalid, it should have been removed\n");
00654 return TRUE;
00655 }
00656 #endif
00657
00658 _dbus_return_val_if_fail (watch->fd >= 0 , TRUE);
00659
00660 _dbus_watch_sanitize_condition (watch, &flags);
00661
00662 if (flags == 0)
00663 {
00664 _dbus_verbose ("After sanitization, watch flags on fd %d were 0\n",
00665 watch->fd);
00666 return TRUE;
00667 }
00668 else
00669 return (* watch->handler) (watch, flags,
00670 watch->handler_data);
00671 }
00672
00673