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 unsigned int oom_last_time : 1;
00054 };
00055
00056 dbus_bool_t
00057 _dbus_watch_get_enabled (DBusWatch *watch)
00058 {
00059 return watch->enabled;
00060 }
00061
00062 dbus_bool_t
00063 _dbus_watch_get_oom_last_time (DBusWatch *watch)
00064 {
00065 return watch->oom_last_time;
00066 }
00067
00068 void
00069 _dbus_watch_set_oom_last_time (DBusWatch *watch,
00070 dbus_bool_t oom)
00071 {
00072 watch->oom_last_time = oom;
00073 }
00074
00087 DBusWatch*
00088 _dbus_watch_new (int fd,
00089 unsigned int flags,
00090 dbus_bool_t enabled,
00091 DBusWatchHandler handler,
00092 void *data,
00093 DBusFreeFunction free_data_function)
00094 {
00095 DBusWatch *watch;
00096
00097 #define VALID_WATCH_FLAGS (DBUS_WATCH_WRITABLE | DBUS_WATCH_READABLE)
00098
00099 _dbus_assert ((flags & VALID_WATCH_FLAGS) == flags);
00100
00101 watch = dbus_new0 (DBusWatch, 1);
00102 if (watch == NULL)
00103 return NULL;
00104
00105 watch->refcount = 1;
00106 watch->fd = fd;
00107 watch->flags = flags;
00108 watch->enabled = enabled;
00109
00110 watch->handler = handler;
00111 watch->handler_data = data;
00112 watch->free_handler_data_function = free_data_function;
00113
00114 return watch;
00115 }
00116
00123 DBusWatch *
00124 _dbus_watch_ref (DBusWatch *watch)
00125 {
00126 watch->refcount += 1;
00127
00128 return watch;
00129 }
00130
00137 void
00138 _dbus_watch_unref (DBusWatch *watch)
00139 {
00140 _dbus_assert (watch != NULL);
00141 _dbus_assert (watch->refcount > 0);
00142
00143 watch->refcount -= 1;
00144 if (watch->refcount == 0)
00145 {
00146 if (watch->fd != -1)
00147 _dbus_warn ("this watch should have been invalidated");
00148
00149 dbus_watch_set_data (watch, NULL, NULL);
00150
00151 if (watch->free_handler_data_function)
00152 (* watch->free_handler_data_function) (watch->handler_data);
00153
00154 dbus_free (watch);
00155 }
00156 }
00157
00168 void
00169 _dbus_watch_invalidate (DBusWatch *watch)
00170 {
00171 watch->fd = -1;
00172 watch->flags = 0;
00173 }
00174
00184 void
00185 _dbus_watch_sanitize_condition (DBusWatch *watch,
00186 unsigned int *condition)
00187 {
00188 if (!(watch->flags & DBUS_WATCH_READABLE))
00189 *condition &= ~DBUS_WATCH_READABLE;
00190 if (!(watch->flags & DBUS_WATCH_WRITABLE))
00191 *condition &= ~DBUS_WATCH_WRITABLE;
00192 }
00193
00194
00214 struct DBusWatchList
00215 {
00216 DBusList *watches;
00218 DBusAddWatchFunction add_watch_function;
00219 DBusRemoveWatchFunction remove_watch_function;
00220 DBusWatchToggledFunction watch_toggled_function;
00221 void *watch_data;
00222 DBusFreeFunction watch_free_data_function;
00223 };
00224
00231 DBusWatchList*
00232 _dbus_watch_list_new (void)
00233 {
00234 DBusWatchList *watch_list;
00235
00236 watch_list = dbus_new0 (DBusWatchList, 1);
00237 if (watch_list == NULL)
00238 return NULL;
00239
00240 return watch_list;
00241 }
00242
00248 void
00249 _dbus_watch_list_free (DBusWatchList *watch_list)
00250 {
00251
00252 _dbus_watch_list_set_functions (watch_list,
00253 NULL, NULL, NULL, NULL, NULL);
00254 _dbus_list_foreach (&watch_list->watches,
00255 (DBusForeachFunction) _dbus_watch_unref,
00256 NULL);
00257 _dbus_list_clear (&watch_list->watches);
00258
00259 dbus_free (watch_list);
00260 }
00261
00276 dbus_bool_t
00277 _dbus_watch_list_set_functions (DBusWatchList *watch_list,
00278 DBusAddWatchFunction add_function,
00279 DBusRemoveWatchFunction remove_function,
00280 DBusWatchToggledFunction toggled_function,
00281 void *data,
00282 DBusFreeFunction free_data_function)
00283 {
00284
00285 if (add_function != NULL)
00286 {
00287 DBusList *link;
00288
00289 link = _dbus_list_get_first_link (&watch_list->watches);
00290 while (link != NULL)
00291 {
00292 DBusList *next = _dbus_list_get_next_link (&watch_list->watches,
00293 link);
00294
00295 #ifdef DBUS_ENABLE_VERBOSE_MODE
00296 {
00297 const char *watch_type;
00298 int flags;
00299
00300 flags = dbus_watch_get_flags (link->data);
00301 if ((flags & DBUS_WATCH_READABLE) &&
00302 (flags & DBUS_WATCH_WRITABLE))
00303 watch_type = "readwrite";
00304 else if (flags & DBUS_WATCH_READABLE)
00305 watch_type = "read";
00306 else if (flags & DBUS_WATCH_WRITABLE)
00307 watch_type = "write";
00308 else
00309 watch_type = "not read or write";
00310
00311 _dbus_verbose ("Adding a %s watch on fd %d using newly-set add watch function\n",
00312 watch_type,
00313 dbus_watch_get_socket (link->data));
00314 }
00315 #endif
00316
00317 if (!(* add_function) (link->data, data))
00318 {
00319
00320 DBusList *link2;
00321
00322 link2 = _dbus_list_get_first_link (&watch_list->watches);
00323 while (link2 != link)
00324 {
00325 DBusList *next = _dbus_list_get_next_link (&watch_list->watches,
00326 link2);
00327
00328 _dbus_verbose ("Removing watch on fd %d using newly-set remove function because initial add failed\n",
00329 dbus_watch_get_socket (link2->data));
00330
00331 (* remove_function) (link2->data, data);
00332
00333 link2 = next;
00334 }
00335
00336 return FALSE;
00337 }
00338
00339 link = next;
00340 }
00341 }
00342
00343
00344
00345 if (watch_list->remove_watch_function != NULL)
00346 {
00347 _dbus_verbose ("Removing all pre-existing watches\n");
00348
00349 _dbus_list_foreach (&watch_list->watches,
00350 (DBusForeachFunction) watch_list->remove_watch_function,
00351 watch_list->watch_data);
00352 }
00353
00354 if (watch_list->watch_free_data_function != NULL)
00355 (* watch_list->watch_free_data_function) (watch_list->watch_data);
00356
00357 watch_list->add_watch_function = add_function;
00358 watch_list->remove_watch_function = remove_function;
00359 watch_list->watch_toggled_function = toggled_function;
00360 watch_list->watch_data = data;
00361 watch_list->watch_free_data_function = free_data_function;
00362
00363 return TRUE;
00364 }
00365
00374 dbus_bool_t
00375 _dbus_watch_list_add_watch (DBusWatchList *watch_list,
00376 DBusWatch *watch)
00377 {
00378 if (!_dbus_list_append (&watch_list->watches, watch))
00379 return FALSE;
00380
00381 _dbus_watch_ref (watch);
00382
00383 if (watch_list->add_watch_function != NULL)
00384 {
00385 _dbus_verbose ("Adding watch on fd %d\n",
00386 dbus_watch_get_socket (watch));
00387
00388 if (!(* watch_list->add_watch_function) (watch,
00389 watch_list->watch_data))
00390 {
00391 _dbus_list_remove_last (&watch_list->watches, watch);
00392 _dbus_watch_unref (watch);
00393 return FALSE;
00394 }
00395 }
00396
00397 return TRUE;
00398 }
00399
00407 void
00408 _dbus_watch_list_remove_watch (DBusWatchList *watch_list,
00409 DBusWatch *watch)
00410 {
00411 if (!_dbus_list_remove (&watch_list->watches, watch))
00412 _dbus_assert_not_reached ("Nonexistent watch was removed");
00413
00414 if (watch_list->remove_watch_function != NULL)
00415 {
00416 _dbus_verbose ("Removing watch on fd %d\n",
00417 dbus_watch_get_socket (watch));
00418
00419 (* watch_list->remove_watch_function) (watch,
00420 watch_list->watch_data);
00421 }
00422
00423 _dbus_watch_unref (watch);
00424 }
00425
00434 void
00435 _dbus_watch_list_toggle_watch (DBusWatchList *watch_list,
00436 DBusWatch *watch,
00437 dbus_bool_t enabled)
00438 {
00439 enabled = !!enabled;
00440
00441 if (enabled == watch->enabled)
00442 return;
00443
00444 watch->enabled = enabled;
00445
00446 if (watch_list->watch_toggled_function != NULL)
00447 {
00448 _dbus_verbose ("Toggling watch %p on fd %d to %d\n",
00449 watch, dbus_watch_get_socket (watch), watch->enabled);
00450
00451 (* watch_list->watch_toggled_function) (watch,
00452 watch_list->watch_data);
00453 }
00454 }
00455
00468 void
00469 _dbus_watch_set_handler (DBusWatch *watch,
00470 DBusWatchHandler handler,
00471 void *data,
00472 DBusFreeFunction free_data_function)
00473 {
00474 if (watch->free_handler_data_function)
00475 (* watch->free_handler_data_function) (watch->handler_data);
00476
00477 watch->handler = handler;
00478 watch->handler_data = data;
00479 watch->free_handler_data_function = free_data_function;
00480 }
00481
00513 int
00514 dbus_watch_get_fd (DBusWatch *watch)
00515 {
00516 _dbus_return_val_if_fail (watch != NULL, -1);
00517
00518 return dbus_watch_get_unix_fd(watch);
00519 }
00520
00534 int
00535 dbus_watch_get_unix_fd (DBusWatch *watch)
00536 {
00537 _dbus_return_val_if_fail (watch != NULL, -1);
00538
00539
00540
00541
00542
00543
00544 #ifdef DBUS_UNIX
00545 return watch->fd;
00546 #else
00547 return dbus_watch_get_socket( watch );
00548 #endif
00549 }
00550
00563 int
00564 dbus_watch_get_socket (DBusWatch *watch)
00565 {
00566 _dbus_return_val_if_fail (watch != NULL, -1);
00567
00568 return watch->fd;
00569 }
00570
00584 unsigned int
00585 dbus_watch_get_flags (DBusWatch *watch)
00586 {
00587 _dbus_return_val_if_fail (watch != NULL, 0);
00588 _dbus_assert ((watch->flags & VALID_WATCH_FLAGS) == watch->flags);
00589
00590 return watch->flags;
00591 }
00592
00600 void*
00601 dbus_watch_get_data (DBusWatch *watch)
00602 {
00603 _dbus_return_val_if_fail (watch != NULL, NULL);
00604
00605 return watch->data;
00606 }
00607
00619 void
00620 dbus_watch_set_data (DBusWatch *watch,
00621 void *data,
00622 DBusFreeFunction free_data_function)
00623 {
00624 _dbus_return_if_fail (watch != NULL);
00625
00626 _dbus_verbose ("Setting watch fd %d data to data = %p function = %p from data = %p function = %p\n",
00627 dbus_watch_get_socket (watch),
00628 data, free_data_function, watch->data, watch->free_data_function);
00629
00630 if (watch->free_data_function != NULL)
00631 (* watch->free_data_function) (watch->data);
00632
00633 watch->data = data;
00634 watch->free_data_function = free_data_function;
00635 }
00636
00644 dbus_bool_t
00645 dbus_watch_get_enabled (DBusWatch *watch)
00646 {
00647 _dbus_return_val_if_fail (watch != NULL, FALSE);
00648
00649 return watch->enabled;
00650 }
00651
00652
00675 dbus_bool_t
00676 dbus_watch_handle (DBusWatch *watch,
00677 unsigned int flags)
00678 {
00679 _dbus_return_val_if_fail (watch != NULL, FALSE);
00680
00681 #ifndef DBUS_DISABLE_CHECKS
00682 if (watch->fd < 0 || watch->flags == 0)
00683 {
00684 _dbus_warn_check_failed ("Watch is invalid, it should have been removed\n");
00685 return TRUE;
00686 }
00687 #endif
00688
00689 _dbus_return_val_if_fail (watch->fd >= 0 , TRUE);
00690
00691 _dbus_watch_sanitize_condition (watch, &flags);
00692
00693 if (flags == 0)
00694 {
00695 _dbus_verbose ("After sanitization, watch flags on fd %d were 0\n",
00696 watch->fd);
00697 return TRUE;
00698 }
00699 else
00700 return (* watch->handler) (watch, flags,
00701 watch->handler_data);
00702 }
00703
00704