Check that watches are removed, then invalidated, then unreffed
[platform/upstream/dbus.git] / dbus / dbus-watch.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-watch.c DBusWatch implementation
3  *
4  * Copyright (C) 2002, 2003  Red Hat Inc.
5  *
6  * Licensed under the Academic Free License version 2.1
7  * 
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  * 
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23
24 #include <config.h>
25 #include "dbus-internals.h"
26 #include "dbus-watch.h"
27 #include "dbus-list.h"
28
29 /**
30  * @defgroup DBusWatchInternals DBusWatch implementation details
31  * @ingroup  DBusInternals
32  * @brief implementation details for DBusWatch
33  * 
34  * @{
35  */
36
37 /**
38  * Implementation of DBusWatch
39  */
40 struct DBusWatch
41 {
42   int refcount;                        /**< Reference count */
43   int fd;                              /**< File descriptor. */
44   unsigned int flags;                  /**< Conditions to watch. */
45
46   DBusWatchHandler handler;                    /**< Watch handler. */
47   void *handler_data;                          /**< Watch handler data. */
48   DBusFreeFunction free_handler_data_function; /**< Free the watch handler data. */
49   
50   void *data;                          /**< Application data. */
51   DBusFreeFunction free_data_function; /**< Free the application data. */
52   unsigned int enabled : 1;            /**< Whether it's enabled. */
53 };
54
55 dbus_bool_t
56 _dbus_watch_get_enabled (DBusWatch *watch)
57 {
58   return watch->enabled;
59 }
60
61 /**
62  * Creates a new DBusWatch. Used to add a file descriptor to be polled
63  * by a main loop.
64  * 
65  * @param fd the file descriptor to be watched.
66  * @param flags the conditions to watch for on the descriptor.
67  * @param enabled the initial enabled state
68  * @param handler the handler function
69  * @param data data for handler function
70  * @param free_data_function function to free the data
71  * @returns the new DBusWatch object.
72  */
73 DBusWatch*
74 _dbus_watch_new (int               fd,
75                  unsigned int      flags,
76                  dbus_bool_t       enabled,
77                  DBusWatchHandler  handler,
78                  void             *data,
79                  DBusFreeFunction  free_data_function)
80 {
81   DBusWatch *watch;
82
83 #define VALID_WATCH_FLAGS (DBUS_WATCH_WRITABLE | DBUS_WATCH_READABLE)
84   
85   _dbus_assert ((flags & VALID_WATCH_FLAGS) == flags);
86   
87   watch = dbus_new0 (DBusWatch, 1);
88   if (watch == NULL)
89     return NULL;
90   
91   watch->refcount = 1;
92   watch->fd = fd;
93   watch->flags = flags;
94   watch->enabled = enabled;
95
96   watch->handler = handler;
97   watch->handler_data = data;
98   watch->free_handler_data_function = free_data_function;
99   
100   return watch;
101 }
102
103 /**
104  * Increments the reference count of a DBusWatch object.
105  *
106  * @param watch the watch object.
107  * @returns the watch object.
108  */
109 DBusWatch *
110 _dbus_watch_ref (DBusWatch *watch)
111 {
112   watch->refcount += 1;
113
114   return watch;
115 }
116
117 /**
118  * Decrements the reference count of a DBusWatch object
119  * and finalizes the object if the count reaches zero.
120  *
121  * @param watch the watch object.
122  */
123 void
124 _dbus_watch_unref (DBusWatch *watch)
125 {
126   _dbus_assert (watch != NULL);
127   _dbus_assert (watch->refcount > 0);
128
129   watch->refcount -= 1;
130   if (watch->refcount == 0)
131     {
132       if (watch->fd != -1)
133         _dbus_warn ("this watch should have been invalidated");
134
135       dbus_watch_set_data (watch, NULL, NULL); /* call free_data_function */
136
137       if (watch->free_handler_data_function)
138         (* watch->free_handler_data_function) (watch->handler_data);
139       
140       dbus_free (watch);
141     }
142 }
143
144 /**
145  * Clears the file descriptor from a now-invalid watch object so that
146  * no one tries to use it.  This is because a watch may stay alive due
147  * to reference counts after the file descriptor is closed.
148  * Invalidation makes it easier to catch bugs. It also
149  * keeps people from doing dorky things like assuming file descriptors
150  * are unique (never recycled).
151  *
152  * @param watch the watch object.
153  */
154 void
155 _dbus_watch_invalidate (DBusWatch *watch)
156 {
157   watch->fd = -1;
158   watch->flags = 0;
159 }
160
161 /**
162  * Sanitizes the given condition so that it only contains
163  * flags that the DBusWatch requested. e.g. if the
164  * watch is a DBUS_WATCH_READABLE watch then
165  * DBUS_WATCH_WRITABLE will be stripped from the condition.
166  *
167  * @param watch the watch object.
168  * @param condition address of the condition to sanitize.
169  */
170 void
171 _dbus_watch_sanitize_condition (DBusWatch    *watch,
172                                 unsigned int *condition)
173 {
174   if (!(watch->flags & DBUS_WATCH_READABLE))
175     *condition &= ~DBUS_WATCH_READABLE;
176   if (!(watch->flags & DBUS_WATCH_WRITABLE))
177     *condition &= ~DBUS_WATCH_WRITABLE;
178 }
179
180
181 /**
182  * @typedef DBusWatchList
183  *
184  * Opaque data type representing a list of watches
185  * and a set of DBusAddWatchFunction/DBusRemoveWatchFunction.
186  * Automatically handles removing/re-adding watches
187  * when the DBusAddWatchFunction is updated or changed.
188  * Holds a reference count to each watch.
189  *
190  * Used in the implementation of both DBusServer and
191  * DBusClient.
192  *
193  */
194
195 /**
196  * DBusWatchList implementation details. All fields
197  * are private.
198  *
199  */
200 struct DBusWatchList
201 {
202   DBusList *watches;           /**< Watch objects. */
203
204   DBusAddWatchFunction add_watch_function;    /**< Callback for adding a watch. */
205   DBusRemoveWatchFunction remove_watch_function; /**< Callback for removing a watch. */
206   DBusWatchToggledFunction watch_toggled_function; /**< Callback on toggling enablement */
207   void *watch_data;                           /**< Data for watch callbacks */
208   DBusFreeFunction watch_free_data_function;  /**< Free function for watch callback data */
209 };
210
211 /**
212  * Creates a new watch list. Returns #NULL if insufficient
213  * memory exists.
214  *
215  * @returns the new watch list, or #NULL on failure.
216  */
217 DBusWatchList*
218 _dbus_watch_list_new (void)
219 {
220   DBusWatchList *watch_list;
221
222   watch_list = dbus_new0 (DBusWatchList, 1);
223   if (watch_list == NULL)
224     return NULL;
225
226   return watch_list;
227 }
228
229 /**
230  * Frees a DBusWatchList.
231  *
232  * @param watch_list the watch list.
233  */
234 void
235 _dbus_watch_list_free (DBusWatchList *watch_list)
236 {
237   /* free watch_data and removes watches as a side effect */
238   _dbus_watch_list_set_functions (watch_list,
239                                   NULL, NULL, NULL, NULL, NULL);
240   _dbus_list_foreach (&watch_list->watches,
241                       (DBusForeachFunction) _dbus_watch_unref,
242                       NULL);
243   _dbus_list_clear (&watch_list->watches);
244
245   dbus_free (watch_list);
246 }
247
248 /**
249  * Sets the watch functions. This function is the "backend"
250  * for dbus_connection_set_watch_functions() and
251  * dbus_server_set_watch_functions().
252  *
253  * @param watch_list the watch list.
254  * @param add_function the add watch function.
255  * @param remove_function the remove watch function.
256  * @param toggled_function function on toggling enabled flag, or #NULL
257  * @param data the data for those functions.
258  * @param free_data_function the function to free the data.
259  * @returns #FALSE if not enough memory
260  *
261  */
262 dbus_bool_t
263 _dbus_watch_list_set_functions (DBusWatchList           *watch_list,
264                                 DBusAddWatchFunction     add_function,
265                                 DBusRemoveWatchFunction  remove_function,
266                                 DBusWatchToggledFunction toggled_function,
267                                 void                    *data,
268                                 DBusFreeFunction         free_data_function)
269 {
270   /* Add watches with the new watch function, failing on OOM */
271   if (add_function != NULL)
272     {
273       DBusList *link;
274       
275       link = _dbus_list_get_first_link (&watch_list->watches);
276       while (link != NULL)
277         {
278           DBusList *next = _dbus_list_get_next_link (&watch_list->watches,
279                                                      link);
280
281 #ifdef DBUS_ENABLE_VERBOSE_MODE
282           {
283             const char *watch_type;
284             int flags;
285
286             flags = dbus_watch_get_flags (link->data);
287             if ((flags & DBUS_WATCH_READABLE) &&
288                 (flags & DBUS_WATCH_WRITABLE))
289               watch_type = "readwrite";
290             else if (flags & DBUS_WATCH_READABLE)
291               watch_type = "read";
292             else if (flags & DBUS_WATCH_WRITABLE)
293               watch_type = "write";
294             else
295               watch_type = "not read or write";
296             
297             _dbus_verbose ("Adding a %s watch on fd %d using newly-set add watch function\n",
298                            watch_type,
299                            dbus_watch_get_socket (link->data));
300           }
301 #endif /* DBUS_ENABLE_VERBOSE_MODE */
302           
303           if (!(* add_function) (link->data, data))
304             {
305               /* remove it all again and return FALSE */
306               DBusList *link2;
307               
308               link2 = _dbus_list_get_first_link (&watch_list->watches);
309               while (link2 != link)
310                 {
311                   DBusList *next = _dbus_list_get_next_link (&watch_list->watches,
312                                                              link2);
313                   
314                   _dbus_verbose ("Removing watch on fd %d using newly-set remove function because initial add failed\n",
315                                  dbus_watch_get_socket (link2->data));
316                   
317                   (* remove_function) (link2->data, data);
318                   
319                   link2 = next;
320                 }
321
322               return FALSE;
323             }
324       
325           link = next;
326         }
327     }
328   
329   /* Remove all current watches from previous watch handlers */
330
331   if (watch_list->remove_watch_function != NULL)
332     {
333       _dbus_verbose ("Removing all pre-existing watches\n");
334       
335       _dbus_list_foreach (&watch_list->watches,
336                           (DBusForeachFunction) watch_list->remove_watch_function,
337                           watch_list->watch_data);
338     }
339
340   if (watch_list->watch_free_data_function != NULL)
341     (* watch_list->watch_free_data_function) (watch_list->watch_data);
342   
343   watch_list->add_watch_function = add_function;
344   watch_list->remove_watch_function = remove_function;
345   watch_list->watch_toggled_function = toggled_function;
346   watch_list->watch_data = data;
347   watch_list->watch_free_data_function = free_data_function;
348
349   return TRUE;
350 }
351
352 /**
353  * Adds a new watch to the watch list, invoking the
354  * application DBusAddWatchFunction if appropriate.
355  *
356  * @param watch_list the watch list.
357  * @param watch the watch to add.
358  * @returns #TRUE on success, #FALSE if no memory.
359  */
360 dbus_bool_t
361 _dbus_watch_list_add_watch (DBusWatchList *watch_list,
362                             DBusWatch     *watch)
363 {
364   if (!_dbus_list_append (&watch_list->watches, watch))
365     return FALSE;
366   
367   _dbus_watch_ref (watch);
368
369   if (watch_list->add_watch_function != NULL)
370     {
371       _dbus_verbose ("Adding watch on fd %d\n",
372                      dbus_watch_get_socket (watch));
373       
374       if (!(* watch_list->add_watch_function) (watch,
375                                                watch_list->watch_data))
376         {
377           _dbus_list_remove_last (&watch_list->watches, watch);
378           _dbus_watch_unref (watch);
379           return FALSE;
380         }
381     }
382   
383   return TRUE;
384 }
385
386 /**
387  * Removes a watch from the watch list, invoking the
388  * application's DBusRemoveWatchFunction if appropriate.
389  *
390  * @param watch_list the watch list.
391  * @param watch the watch to remove.
392  */
393 void
394 _dbus_watch_list_remove_watch  (DBusWatchList *watch_list,
395                                 DBusWatch     *watch)
396 {
397   if (!_dbus_list_remove (&watch_list->watches, watch))
398     _dbus_assert_not_reached ("Nonexistent watch was removed");
399   
400   if (watch_list->remove_watch_function != NULL)
401     {
402       _dbus_verbose ("Removing watch on fd %d\n",
403                      dbus_watch_get_socket (watch));
404       
405       (* watch_list->remove_watch_function) (watch,
406                                              watch_list->watch_data);
407     }
408   
409   _dbus_watch_unref (watch);
410 }
411
412 /**
413  * Sets a watch to the given enabled state, invoking the
414  * application's DBusWatchToggledFunction if appropriate.
415  *
416  * @param watch_list the watch list.
417  * @param watch the watch to toggle.
418  * @param enabled #TRUE to enable
419  */
420 void
421 _dbus_watch_list_toggle_watch (DBusWatchList           *watch_list,
422                                DBusWatch               *watch,
423                                dbus_bool_t              enabled)
424 {
425   enabled = !!enabled;
426   
427   if (enabled == watch->enabled)
428     return;
429
430   watch->enabled = enabled;
431   
432   if (watch_list->watch_toggled_function != NULL)
433     {
434       _dbus_verbose ("Toggling watch %p on fd %d to %d\n",
435                      watch, dbus_watch_get_socket (watch), watch->enabled);
436       
437       (* watch_list->watch_toggled_function) (watch,
438                                               watch_list->watch_data);
439     }
440 }
441
442 /**
443  * Sets the handler for the watch.
444  *
445  * @todo this function only exists because of the weird
446  * way connection watches are done, see the note
447  * in docs for _dbus_connection_handle_watch().
448  *
449  * @param watch the watch
450  * @param handler the new handler
451  * @param data the data
452  * @param free_data_function free data with this
453  */
454 void
455 _dbus_watch_set_handler (DBusWatch        *watch,
456                          DBusWatchHandler  handler,
457                          void             *data,
458                          DBusFreeFunction  free_data_function)
459 {
460   if (watch->free_handler_data_function)
461     (* watch->free_handler_data_function) (watch->handler_data);
462
463   watch->handler = handler;
464   watch->handler_data = data;
465   watch->free_handler_data_function = free_data_function;
466 }
467
468 /** @} */
469
470 /**
471  * @defgroup DBusWatch DBusWatch
472  * @ingroup  DBus
473  * @brief Object representing a file descriptor to be watched.
474  *
475  * Types and functions related to DBusWatch. A watch represents
476  * a file descriptor that the main loop needs to monitor,
477  * as in Qt's QSocketNotifier or GLib's g_io_add_watch().
478  *
479  * Use dbus_connection_set_watch_functions() or dbus_server_set_watch_functions()
480  * to be notified when libdbus needs to add or remove watches.
481  * 
482  * @{
483  */
484
485 /**
486  * @typedef DBusWatch
487  *
488  * Opaque object representing a file descriptor
489  * to be watched for changes in readability,
490  * writability, or hangup.
491  */
492
493 /**
494  * Deprecated former name of dbus_watch_get_unix_fd().
495  * 
496  * @param watch the DBusWatch object.
497  * @returns the file descriptor to watch.
498  */
499 int
500 dbus_watch_get_fd (DBusWatch *watch)
501 {
502   _dbus_return_val_if_fail (watch != NULL, -1);
503
504   return dbus_watch_get_unix_fd(watch);
505 }
506
507 /**
508  * Returns a UNIX file descriptor to be watched,
509  * which may be a pipe, socket, or other type of
510  * descriptor. On UNIX this is preferred to
511  * dbus_watch_get_socket() since it works with
512  * more kinds of #DBusWatch.
513  *
514  * Always returns -1 on Windows. On Windows you use
515  * dbus_watch_get_socket() to get a Winsock socket to watch.
516  * 
517  * @param watch the DBusWatch object.
518  * @returns the file descriptor to watch.
519  */
520 int
521 dbus_watch_get_unix_fd (DBusWatch *watch)
522 {
523   _dbus_return_val_if_fail (watch != NULL, -1);
524
525   /* FIXME remove #ifdef and do this on a lower level
526    * (watch should have set_socket and set_unix_fd and track
527    * which it has, and the transport should provide the
528    * appropriate watch type)
529    */
530 #ifdef DBUS_UNIX
531   return watch->fd;
532 #else
533   return dbus_watch_get_socket( watch );
534 #endif
535 }
536
537 /**
538  * Returns a socket to be watched, on UNIX this will return -1 if our
539  * transport is not socket-based so dbus_watch_get_unix_fd() is
540  * preferred.
541  *
542  * On Windows, dbus_watch_get_unix_fd() returns -1 but this function
543  * returns a Winsock socket (assuming the transport is socket-based,
544  * as it always is for now).
545  * 
546  * @param watch the DBusWatch object.
547  * @returns the socket to watch.
548  */
549 int
550 dbus_watch_get_socket (DBusWatch *watch)
551 {
552   _dbus_return_val_if_fail (watch != NULL, -1);
553
554   return watch->fd;
555 }
556
557 /**
558  * Gets flags from DBusWatchFlags indicating
559  * what conditions should be monitored on the
560  * file descriptor.
561  * 
562  * The flags returned will only contain DBUS_WATCH_READABLE
563  * and DBUS_WATCH_WRITABLE, never DBUS_WATCH_HANGUP or
564  * DBUS_WATCH_ERROR; all watches implicitly include a watch
565  * for hangups, errors, and other exceptional conditions.
566  *
567  * @param watch the DBusWatch object.
568  * @returns the conditions to watch.
569  */
570 unsigned int
571 dbus_watch_get_flags (DBusWatch *watch)
572 {
573   _dbus_return_val_if_fail (watch != NULL, 0);
574   _dbus_assert ((watch->flags & VALID_WATCH_FLAGS) == watch->flags);
575
576   return watch->flags;
577 }
578
579 /**
580  * Gets data previously set with dbus_watch_set_data()
581  * or #NULL if none.
582  *
583  * @param watch the DBusWatch object.
584  * @returns previously-set data.
585  */
586 void*
587 dbus_watch_get_data (DBusWatch *watch)
588 {
589   _dbus_return_val_if_fail (watch != NULL, NULL);
590
591   return watch->data;
592 }
593
594 /**
595  * Sets data which can be retrieved with dbus_watch_get_data().
596  * Intended for use by the DBusAddWatchFunction and
597  * DBusRemoveWatchFunction to store their own data.  For example with
598  * Qt you might store the QSocketNotifier for this watch and with GLib
599  * you might store a GSource.
600  *
601  * @param watch the DBusWatch object.
602  * @param data the data.
603  * @param free_data_function function to be called to free the data.
604  */
605 void
606 dbus_watch_set_data (DBusWatch        *watch,
607                      void             *data,
608                      DBusFreeFunction  free_data_function)
609 {
610   _dbus_return_if_fail (watch != NULL);
611
612   _dbus_verbose ("Setting watch fd %d data to data = %p function = %p from data = %p function = %p\n",
613                  dbus_watch_get_socket (watch),
614                  data, free_data_function, watch->data, watch->free_data_function);
615   
616   if (watch->free_data_function != NULL)
617     (* watch->free_data_function) (watch->data);
618   
619   watch->data = data;
620   watch->free_data_function = free_data_function;
621 }
622
623 /**
624  * Returns whether a watch is enabled or not. If not
625  * enabled, it should not be polled by the main loop.
626  *
627  * @param watch the DBusWatch object
628  * @returns #TRUE if the watch is enabled
629  */
630 dbus_bool_t
631 dbus_watch_get_enabled (DBusWatch *watch)
632 {
633   _dbus_return_val_if_fail (watch != NULL, FALSE);
634
635   return watch->enabled;
636 }
637
638
639 /**
640  * Called to notify the D-Bus library when a previously-added watch is
641  * ready for reading or writing, or has an exception such as a hangup.
642  * 
643  * If this function returns #FALSE, then the file descriptor may still
644  * be ready for reading or writing, but more memory is needed in order
645  * to do the reading or writing. If you ignore the #FALSE return, your
646  * application may spin in a busy loop on the file descriptor until
647  * memory becomes available, but nothing more catastrophic should
648  * happen.
649  *
650  * dbus_watch_handle() cannot be called during the
651  * DBusAddWatchFunction, as the connection will not be ready to handle
652  * that watch yet.
653  * 
654  * It is not allowed to reference a DBusWatch after it has been passed
655  * to remove_function.
656  *
657  * @param watch the DBusWatch object.
658  * @param flags the poll condition using #DBusWatchFlags values
659  * @returns #FALSE if there wasn't enough memory 
660  */
661 dbus_bool_t
662 dbus_watch_handle (DBusWatch    *watch,
663                    unsigned int  flags)
664 {
665   _dbus_return_val_if_fail (watch != NULL, FALSE);
666
667 #ifndef DBUS_DISABLE_CHECKS
668   if (watch->fd < 0 || watch->flags == 0)
669     {
670       _dbus_warn_check_failed ("Watch is invalid, it should have been removed\n");
671       return TRUE;
672     }
673 #endif
674     
675   _dbus_return_val_if_fail (watch->fd >= 0 /* fails if watch was removed */, TRUE);
676   
677   _dbus_watch_sanitize_condition (watch, &flags);
678
679   if (flags == 0)
680     {
681       _dbus_verbose ("After sanitization, watch flags on fd %d were 0\n",
682                      watch->fd);
683       return TRUE;
684     }
685   else
686     return (* watch->handler) (watch, flags,
687                                watch->handler_data);
688 }
689
690
691 /** @} */