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