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
00066 DBusWatch*
00067 _dbus_watch_new (int fd,
00068 unsigned int flags,
00069 dbus_bool_t enabled,
00070 DBusWatchHandler handler,
00071 void *data,
00072 DBusFreeFunction free_data_function)
00073 {
00074 DBusWatch *watch;
00075
00076 #define VALID_WATCH_FLAGS (DBUS_WATCH_WRITABLE | DBUS_WATCH_READABLE)
00077
00078 _dbus_assert ((flags & VALID_WATCH_FLAGS) == flags);
00079
00080 watch = dbus_new0 (DBusWatch, 1);
00081 if (watch == NULL)
00082 return NULL;
00083
00084 watch->refcount = 1;
00085 watch->fd = fd;
00086 watch->flags = flags;
00087 watch->enabled = enabled;
00088
00089 watch->handler = handler;
00090 watch->handler_data = data;
00091 watch->free_handler_data_function = free_data_function;
00092
00093 return watch;
00094 }
00095
00102 DBusWatch *
00103 _dbus_watch_ref (DBusWatch *watch)
00104 {
00105 watch->refcount += 1;
00106
00107 return watch;
00108 }
00109
00116 void
00117 _dbus_watch_unref (DBusWatch *watch)
00118 {
00119 _dbus_assert (watch != NULL);
00120 _dbus_assert (watch->refcount > 0);
00121
00122 watch->refcount -= 1;
00123 if (watch->refcount == 0)
00124 {
00125 dbus_watch_set_data (watch, NULL, NULL);
00126
00127 if (watch->free_handler_data_function)
00128 (* watch->free_handler_data_function) (watch->handler_data);
00129
00130 dbus_free (watch);
00131 }
00132 }
00133
00144 void
00145 _dbus_watch_invalidate (DBusWatch *watch)
00146 {
00147 watch->fd = -1;
00148 watch->flags = 0;
00149 }
00150
00160 void
00161 _dbus_watch_sanitize_condition (DBusWatch *watch,
00162 unsigned int *condition)
00163 {
00164 if (!(watch->flags & DBUS_WATCH_READABLE))
00165 *condition &= ~DBUS_WATCH_READABLE;
00166 if (!(watch->flags & DBUS_WATCH_WRITABLE))
00167 *condition &= ~DBUS_WATCH_WRITABLE;
00168 }
00169
00170
00190 struct DBusWatchList
00191 {
00192 DBusList *watches;
00194 DBusAddWatchFunction add_watch_function;
00195 DBusRemoveWatchFunction remove_watch_function;
00196 DBusWatchToggledFunction watch_toggled_function;
00197 void *watch_data;
00198 DBusFreeFunction watch_free_data_function;
00199 };
00200
00207 DBusWatchList*
00208 _dbus_watch_list_new (void)
00209 {
00210 DBusWatchList *watch_list;
00211
00212 watch_list = dbus_new0 (DBusWatchList, 1);
00213 if (watch_list == NULL)
00214 return NULL;
00215
00216 return watch_list;
00217 }
00218
00224 void
00225 _dbus_watch_list_free (DBusWatchList *watch_list)
00226 {
00227
00228 _dbus_watch_list_set_functions (watch_list,
00229 NULL, NULL, NULL, NULL, NULL);
00230 _dbus_list_foreach (&watch_list->watches,
00231 (DBusForeachFunction) _dbus_watch_unref,
00232 NULL);
00233 _dbus_list_clear (&watch_list->watches);
00234
00235 dbus_free (watch_list);
00236 }
00237
00252 dbus_bool_t
00253 _dbus_watch_list_set_functions (DBusWatchList *watch_list,
00254 DBusAddWatchFunction add_function,
00255 DBusRemoveWatchFunction remove_function,
00256 DBusWatchToggledFunction toggled_function,
00257 void *data,
00258 DBusFreeFunction free_data_function)
00259 {
00260
00261 if (add_function != NULL)
00262 {
00263 DBusList *link;
00264
00265 link = _dbus_list_get_first_link (&watch_list->watches);
00266 while (link != NULL)
00267 {
00268 DBusList *next = _dbus_list_get_next_link (&watch_list->watches,
00269 link);
00270
00271 #ifdef DBUS_ENABLE_VERBOSE_MODE
00272 {
00273 const char *watch_type;
00274 int flags;
00275
00276 flags = dbus_watch_get_flags (link->data);
00277 if ((flags & DBUS_WATCH_READABLE) &&
00278 (flags & DBUS_WATCH_WRITABLE))
00279 watch_type = "readwrite";
00280 else if (flags & DBUS_WATCH_READABLE)
00281 watch_type = "read";
00282 else if (flags & DBUS_WATCH_WRITABLE)
00283 watch_type = "write";
00284 else
00285 watch_type = "not read or write";
00286
00287 _dbus_verbose ("Adding a %s watch on fd %d using newly-set add watch function\n",
00288 watch_type,
00289 dbus_watch_get_socket (link->data));
00290 }
00291 #endif
00292
00293 if (!(* add_function) (link->data, data))
00294 {
00295
00296 DBusList *link2;
00297
00298 link2 = _dbus_list_get_first_link (&watch_list->watches);
00299 while (link2 != link)
00300 {
00301 DBusList *next = _dbus_list_get_next_link (&watch_list->watches,
00302 link2);
00303
00304 _dbus_verbose ("Removing watch on fd %d using newly-set remove function because initial add failed\n",
00305 dbus_watch_get_socket (link2->data));
00306
00307 (* remove_function) (link2->data, data);
00308
00309 link2 = next;
00310 }
00311
00312 return FALSE;
00313 }
00314
00315 link = next;
00316 }
00317 }
00318
00319
00320
00321 if (watch_list->remove_watch_function != NULL)
00322 {
00323 _dbus_verbose ("Removing all pre-existing watches\n");
00324
00325 _dbus_list_foreach (&watch_list->watches,
00326 (DBusForeachFunction) watch_list->remove_watch_function,
00327 watch_list->watch_data);
00328 }
00329
00330 if (watch_list->watch_free_data_function != NULL)
00331 (* watch_list->watch_free_data_function) (watch_list->watch_data);
00332
00333 watch_list->add_watch_function = add_function;
00334 watch_list->remove_watch_function = remove_function;
00335 watch_list->watch_toggled_function = toggled_function;
00336 watch_list->watch_data = data;
00337 watch_list->watch_free_data_function = free_data_function;
00338
00339 return TRUE;
00340 }
00341
00350 dbus_bool_t
00351 _dbus_watch_list_add_watch (DBusWatchList *watch_list,
00352 DBusWatch *watch)
00353 {
00354 if (!_dbus_list_append (&watch_list->watches, watch))
00355 return FALSE;
00356
00357 _dbus_watch_ref (watch);
00358
00359 if (watch_list->add_watch_function != NULL)
00360 {
00361 _dbus_verbose ("Adding watch on fd %d\n",
00362 dbus_watch_get_socket (watch));
00363
00364 if (!(* watch_list->add_watch_function) (watch,
00365 watch_list->watch_data))
00366 {
00367 _dbus_list_remove_last (&watch_list->watches, watch);
00368 _dbus_watch_unref (watch);
00369 return FALSE;
00370 }
00371 }
00372
00373 return TRUE;
00374 }
00375
00383 void
00384 _dbus_watch_list_remove_watch (DBusWatchList *watch_list,
00385 DBusWatch *watch)
00386 {
00387 if (!_dbus_list_remove (&watch_list->watches, watch))
00388 _dbus_assert_not_reached ("Nonexistent watch was removed");
00389
00390 if (watch_list->remove_watch_function != NULL)
00391 {
00392 _dbus_verbose ("Removing watch on fd %d\n",
00393 dbus_watch_get_socket (watch));
00394
00395 (* watch_list->remove_watch_function) (watch,
00396 watch_list->watch_data);
00397 }
00398
00399 _dbus_watch_unref (watch);
00400 }
00401
00410 void
00411 _dbus_watch_list_toggle_watch (DBusWatchList *watch_list,
00412 DBusWatch *watch,
00413 dbus_bool_t enabled)
00414 {
00415 enabled = !!enabled;
00416
00417 if (enabled == watch->enabled)
00418 return;
00419
00420 watch->enabled = enabled;
00421
00422 if (watch_list->watch_toggled_function != NULL)
00423 {
00424 _dbus_verbose ("Toggling watch %p on fd %d to %d\n",
00425 watch, dbus_watch_get_socket (watch), watch->enabled);
00426
00427 (* watch_list->watch_toggled_function) (watch,
00428 watch_list->watch_data);
00429 }
00430 }
00431
00439 void
00440 _dbus_watch_list_toggle_all_watches (DBusWatchList *watch_list,
00441 dbus_bool_t enabled)
00442 {
00443 DBusList *link;
00444
00445 for (link = _dbus_list_get_first_link (&watch_list->watches);
00446 link != NULL;
00447 link = _dbus_list_get_next_link (&watch_list->watches, link))
00448 {
00449 _dbus_watch_list_toggle_watch (watch_list, link->data, enabled);
00450 }
00451 }
00452
00465 void
00466 _dbus_watch_set_handler (DBusWatch *watch,
00467 DBusWatchHandler handler,
00468 void *data,
00469 DBusFreeFunction free_data_function)
00470 {
00471 if (watch->free_handler_data_function)
00472 (* watch->free_handler_data_function) (watch->handler_data);
00473
00474 watch->handler = handler;
00475 watch->handler_data = data;
00476 watch->free_handler_data_function = free_data_function;
00477 }
00478
00510 int
00511 dbus_watch_get_fd (DBusWatch *watch)
00512 {
00513 return dbus_watch_get_unix_fd(watch);
00514 }
00515
00529 int
00530 dbus_watch_get_unix_fd (DBusWatch *watch)
00531 {
00532
00533
00534
00535
00536
00537 #ifdef DBUS_UNIX
00538 return watch->fd;
00539 #else
00540 return -1;
00541 #endif
00542 }
00543
00556 int
00557 dbus_watch_get_socket (DBusWatch *watch)
00558 {
00559 return watch->fd;
00560 }
00561
00575 unsigned int
00576 dbus_watch_get_flags (DBusWatch *watch)
00577 {
00578 _dbus_assert ((watch->flags & VALID_WATCH_FLAGS) == watch->flags);
00579
00580 return watch->flags;
00581 }
00582
00590 void*
00591 dbus_watch_get_data (DBusWatch *watch)
00592 {
00593 return watch->data;
00594 }
00595
00607 void
00608 dbus_watch_set_data (DBusWatch *watch,
00609 void *data,
00610 DBusFreeFunction free_data_function)
00611 {
00612 _dbus_verbose ("Setting watch fd %d data to data = %p function = %p from data = %p function = %p\n",
00613 dbus_watch_get_socket (watch),
00614 data, free_data_function, watch->data, watch->free_data_function);
00615
00616 if (watch->free_data_function != NULL)
00617 (* watch->free_data_function) (watch->data);
00618
00619 watch->data = data;
00620 watch->free_data_function = free_data_function;
00621 }
00622
00630 dbus_bool_t
00631 dbus_watch_get_enabled (DBusWatch *watch)
00632 {
00633 _dbus_assert (watch != NULL);
00634 return watch->enabled;
00635 }
00636
00637
00660 dbus_bool_t
00661 dbus_watch_handle (DBusWatch *watch,
00662 unsigned int flags)
00663 {
00664 #ifndef DBUS_DISABLE_CHECKS
00665 if (watch->fd < 0 || watch->flags == 0)
00666 {
00667 _dbus_warn_check_failed ("%s: Watch is invalid, it should have been removed\n",
00668 _DBUS_FUNCTION_NAME);
00669 return TRUE;
00670 }
00671 #endif
00672
00673 _dbus_return_val_if_fail (watch->fd >= 0 , TRUE);
00674
00675 _dbus_watch_sanitize_condition (watch, &flags);
00676
00677 if (flags == 0)
00678 {
00679 _dbus_verbose ("After sanitization, watch flags on fd %d were 0\n",
00680 watch->fd);
00681 return TRUE;
00682 }
00683 else
00684 return (* watch->handler) (watch, flags,
00685 watch->handler_data);
00686 }
00687
00688