LCOV - code coverage report
Current view: top level - sbus - sssd_dbus_common.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 137 0.0 %
Date: 2016-06-29 Functions: 0 11 0.0 %

          Line data    Source code
       1             : /*
       2             :     Authors:
       3             :         Simo Sorce <ssorce@redhat.com>
       4             :         Stephen Gallagher <sgallagh@redhat.com>
       5             : 
       6             :     Copyright (C) 2009 Red Hat
       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 3 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, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include <sys/time.h>
      23             : #include <tevent.h>
      24             : #include <dbus/dbus.h>
      25             : 
      26             : #include "util/util.h"
      27             : #include "sbus/sssd_dbus.h"
      28             : #include "sbus/sssd_dbus_private.h"
      29             : 
      30             : /* =Watches=============================================================== */
      31             : 
      32             : /* DBUS may ask us to add a watch to a file descriptor that already had a watch
      33             :  * associated. Need to check if that's the case */
      34           0 : static struct sbus_watch_ctx *fd_to_watch(struct sbus_watch_ctx *list, int fd)
      35             : {
      36             :     struct sbus_watch_ctx *watch_iter;
      37             : 
      38           0 :     watch_iter = list;
      39           0 :     while (watch_iter != NULL) {
      40           0 :         if (watch_iter->fd == fd) {
      41           0 :             return watch_iter;
      42             :         }
      43             : 
      44           0 :         watch_iter = watch_iter->next;
      45             :     }
      46             : 
      47           0 :     return NULL;
      48             : }
      49             : 
      50           0 : static int watch_destructor(void *mem)
      51             : {
      52             :     struct sbus_watch_ctx *watch;
      53             : 
      54           0 :     watch = talloc_get_type(mem, struct sbus_watch_ctx);
      55           0 :     DLIST_REMOVE(watch->conn->watch_list, watch);
      56             : 
      57           0 :     return 0;
      58             : }
      59             : 
      60             : /*
      61             :  * watch_handler
      62             :  * Callback for D-BUS to handle messages on a file-descriptor
      63             :  */
      64           0 : static void sbus_watch_handler(struct tevent_context *ev,
      65             :                                struct tevent_fd *fde,
      66             :                                uint16_t flags, void *data)
      67             : {
      68           0 :     struct sbus_watch_ctx *watch = talloc_get_type(data,
      69             :                                                    struct sbus_watch_ctx);
      70             :     enum dbus_conn_type type;
      71             :     union dbus_conn_pointer dbus_p;
      72             : 
      73             :     /* conn may get freed inside a handle, save the data we need for later */
      74           0 :     type = watch->conn->type;
      75           0 :     dbus_p = watch->conn->dbus;
      76             : 
      77             :     /* Take a reference while handling watch */
      78           0 :     if (type == SBUS_SERVER) {
      79           0 :         dbus_server_ref(dbus_p.server);
      80             :     } else {
      81           0 :         dbus_connection_ref(dbus_p.conn);
      82             :     }
      83             : 
      84             :     /* Fire if readable */
      85           0 :     if (flags & TEVENT_FD_READ) {
      86           0 :         if (watch->dbus_read_watch) {
      87           0 :             dbus_watch_handle(watch->dbus_read_watch, DBUS_WATCH_READABLE);
      88             :         }
      89             :     }
      90             : 
      91             :     /* Fire if writeable */
      92           0 :     if (flags & TEVENT_FD_WRITE) {
      93           0 :         if (watch->dbus_write_watch) {
      94           0 :             dbus_watch_handle(watch->dbus_write_watch, DBUS_WATCH_WRITABLE);
      95             :         }
      96             :     }
      97             : 
      98             :     /* Release reference once done */
      99           0 :     if (type == SBUS_SERVER) {
     100           0 :         dbus_server_unref(dbus_p.server);
     101             :     } else {
     102           0 :         dbus_connection_unref(dbus_p.conn);
     103             :     }
     104           0 : }
     105             : 
     106             : /*
     107             :  * add_watch
     108             :  * Set up hooks into the libevents mainloop for
     109             :  * D-BUS to add file descriptor-based events
     110             :  */
     111           0 : dbus_bool_t sbus_add_watch(DBusWatch *dbus_watch, void *data)
     112             : {
     113             :     unsigned int flags;
     114             :     uint16_t event_flags;
     115             :     struct sbus_connection *conn;
     116             :     struct sbus_watch_ctx *watch;
     117             :     dbus_bool_t enabled;
     118             :     int fd;
     119             : 
     120           0 :     conn = talloc_get_type(data, struct sbus_connection);
     121             : 
     122             : #ifdef HAVE_DBUS_WATCH_GET_UNIX_FD
     123           0 :     fd = dbus_watch_get_unix_fd(dbus_watch);
     124             : #else
     125             :     fd = dbus_watch_get_fd(dbus_watch);
     126             : #endif
     127             : 
     128           0 :     watch = fd_to_watch(conn->watch_list, fd);
     129           0 :     if (!watch) {
     130             :         /* does not exist, allocate new one */
     131           0 :         watch = talloc_zero(conn, struct sbus_watch_ctx);
     132           0 :         if (!watch) {
     133           0 :             DEBUG(SSSDBG_FATAL_FAILURE, "Out of Memory!\n");
     134           0 :             return FALSE;
     135             :         }
     136           0 :         watch->conn = conn;
     137           0 :         watch->fd = fd;
     138             :     }
     139             : 
     140           0 :     enabled = dbus_watch_get_enabled(dbus_watch);
     141           0 :     flags = dbus_watch_get_flags(dbus_watch);
     142             : 
     143             :     /* Save the event to the watch object so it can be found later */
     144           0 :     if (flags & DBUS_WATCH_READABLE) {
     145           0 :         watch->dbus_read_watch = dbus_watch;
     146             :     }
     147           0 :     if (flags & DBUS_WATCH_WRITABLE) {
     148           0 :         watch->dbus_write_watch = dbus_watch;
     149             :     }
     150           0 :     dbus_watch_set_data(dbus_watch, watch, NULL);
     151             : 
     152           0 :     if (watch->fde) {
     153             :         /* pre-existing event, just toggle flags */
     154           0 :         sbus_toggle_watch(dbus_watch, data);
     155           0 :         return TRUE;
     156             :     }
     157             : 
     158           0 :     event_flags = 0;
     159           0 :     if (enabled) {
     160           0 :         if (flags & DBUS_WATCH_READABLE) {
     161           0 :             event_flags |= TEVENT_FD_READ;
     162             :         }
     163           0 :         if (flags & DBUS_WATCH_WRITABLE) {
     164           0 :             event_flags |= TEVENT_FD_WRITE;
     165             :         }
     166             :     }
     167             : 
     168             :     /* Add the file descriptor to the event loop */
     169           0 :     watch->fde = tevent_add_fd(conn->ev,
     170             :                                watch, fd, event_flags,
     171             :                                sbus_watch_handler, watch);
     172           0 :     if (!watch->fde) {
     173           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Failed to set up fd event!\n");
     174           0 :         talloc_zfree(watch);
     175           0 :         return FALSE;
     176             :     }
     177             : 
     178           0 :     DLIST_ADD(conn->watch_list, watch);
     179           0 :     talloc_set_destructor((TALLOC_CTX *)watch, watch_destructor);
     180             : 
     181           0 :     DEBUG(SSSDBG_TRACE_INTERNAL, "%p/%p (%d), %s/%s (%s)\n",
     182             :               watch, dbus_watch, fd,
     183             :               ((flags & DBUS_WATCH_READABLE)?"R":"-"),
     184             :               ((flags & DBUS_WATCH_WRITABLE)?"W":"-"),
     185             :               enabled?"enabled":"disabled");
     186             : 
     187           0 :     return TRUE;
     188             : }
     189             : 
     190             : /*
     191             :  * toggle_watch
     192             :  * Hook for D-BUS to toggle the enabled/disabled state of
     193             :  * an event in the mainloop
     194             :  */
     195           0 : void sbus_toggle_watch(DBusWatch *dbus_watch, void *data)
     196             : {
     197             :     struct sbus_watch_ctx *watch;
     198             :     unsigned int flags;
     199             :     dbus_bool_t enabled;
     200             :     void *watch_data;
     201           0 :     int fd = -1;
     202             : 
     203           0 :     enabled = dbus_watch_get_enabled(dbus_watch);
     204           0 :     flags = dbus_watch_get_flags(dbus_watch);
     205             : 
     206           0 :     watch_data = dbus_watch_get_data(dbus_watch);
     207           0 :     watch = talloc_get_type(watch_data, struct sbus_watch_ctx);
     208           0 :     if (!watch) {
     209           0 :         DEBUG(SSSDBG_OP_FAILURE,
     210             :               "[%p] does not carry watch context?!\n", dbus_watch);
     211             :         /* abort ? */
     212           0 :         return;
     213             :     }
     214             : 
     215           0 :     if (enabled) {
     216           0 :         if (flags & DBUS_WATCH_READABLE) {
     217           0 :             TEVENT_FD_READABLE(watch->fde);
     218             :         }
     219           0 :         if (flags & DBUS_WATCH_WRITABLE) {
     220           0 :             TEVENT_FD_WRITEABLE(watch->fde);
     221             :         }
     222             :     } else {
     223           0 :         if (flags & DBUS_WATCH_READABLE) {
     224           0 :             TEVENT_FD_NOT_READABLE(watch->fde);
     225             :         }
     226           0 :         if (flags & DBUS_WATCH_WRITABLE) {
     227           0 :             TEVENT_FD_NOT_WRITEABLE(watch->fde);
     228             :         }
     229             :     }
     230             : 
     231           0 :     if (DEBUG_IS_SET(SSSDBG_TRACE_ALL)) {
     232             : #ifdef HAVE_DBUS_WATCH_GET_UNIX_FD
     233           0 :         fd = dbus_watch_get_unix_fd(dbus_watch);
     234             : #else
     235             :         fd = dbus_watch_get_fd(dbus_watch);
     236             : #endif
     237             :     }
     238           0 :     DEBUG(SSSDBG_TRACE_ALL,
     239             :           "%p/%p (%d), %s/%s (%s)\n",
     240             :            watch, dbus_watch, fd,
     241             :            ((flags & DBUS_WATCH_READABLE)?"R":"-"),
     242             :            ((flags & DBUS_WATCH_WRITABLE)?"W":"-"),
     243             :            enabled?"enabled":"disabled");
     244             : }
     245             : 
     246             : /*
     247             :  * sbus_remove_watch
     248             :  * Hook for D-BUS to remove file descriptor-based events
     249             :  * from the libevents mainloop
     250             :  */
     251           0 : void sbus_remove_watch(DBusWatch *dbus_watch, void *data)
     252             : {
     253             :     struct sbus_watch_ctx *watch;
     254             :     void *watch_data;
     255             : 
     256           0 :     watch_data = dbus_watch_get_data(dbus_watch);
     257           0 :     watch = talloc_get_type(watch_data, struct sbus_watch_ctx);
     258             : 
     259           0 :     DEBUG(SSSDBG_TRACE_INTERNAL, "%p/%p\n", watch, dbus_watch);
     260             : 
     261           0 :     if (!watch) {
     262           0 :         DEBUG(SSSDBG_OP_FAILURE, "DBUS trying to remove unknown watch!\n");
     263           0 :         return;
     264             :     }
     265             : 
     266             :     /* remove dbus watch data */
     267           0 :     dbus_watch_set_data(dbus_watch, NULL, NULL);
     268             : 
     269             :     /* check which watch to remove, or free if none left */
     270           0 :     if (watch->dbus_read_watch == dbus_watch) {
     271           0 :         watch->dbus_read_watch = NULL;
     272             :     }
     273           0 :     if (watch->dbus_write_watch == dbus_watch) {
     274           0 :         watch->dbus_write_watch = NULL;
     275             :     }
     276           0 :     if (!watch->dbus_read_watch && !watch->dbus_write_watch) {
     277           0 :         talloc_free(watch);
     278             :     }
     279             : }
     280             : 
     281             : /* =Timeouts============================================================== */
     282             : 
     283           0 : static struct timeval _get_interval_tv(int interval) {
     284             :     struct timeval tv;
     285             :     struct timeval rightnow;
     286             : 
     287           0 :     gettimeofday(&rightnow,NULL);
     288             : 
     289           0 :     tv.tv_sec = interval / 1000 + rightnow.tv_sec;
     290           0 :     tv.tv_usec = (interval % 1000) * 1000 + rightnow.tv_usec;
     291           0 :     return tv;
     292             : }
     293             : 
     294             : /*
     295             :  * timeout_handler
     296             :  * Callback for D-BUS to handle timed events
     297             :  */
     298           0 : static void sbus_timeout_handler(struct tevent_context *ev,
     299             :                                  struct tevent_timer *te,
     300             :                                  struct timeval t, void *data)
     301             : {
     302             :     struct sbus_timeout_ctx *timeout;
     303           0 :     timeout = talloc_get_type(data, struct sbus_timeout_ctx);
     304             : 
     305           0 :     dbus_timeout_handle(timeout->dbus_timeout);
     306           0 : }
     307             : 
     308             : /*
     309             :  * add_timeout
     310             :  * Hook for D-BUS to add time-based events to the mainloop
     311             :  */
     312           0 : dbus_bool_t sbus_add_timeout(DBusTimeout *dbus_timeout, void *data)
     313             : {
     314             :     struct sbus_connection *conn;
     315             :     struct sbus_timeout_ctx *timeout;
     316             :     struct timeval tv;
     317             : 
     318           0 :     DEBUG(SSSDBG_TRACE_INTERNAL, "%p\n", dbus_timeout);
     319             : 
     320           0 :     if (!dbus_timeout_get_enabled(dbus_timeout)) {
     321           0 :         return TRUE;
     322             :     }
     323             : 
     324           0 :     conn = talloc_get_type(data, struct sbus_connection);
     325             : 
     326           0 :     timeout = talloc_zero(conn, struct sbus_timeout_ctx);
     327           0 :     if (!timeout) {
     328           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Out of Memory!\n");
     329           0 :         return FALSE;
     330             :     }
     331           0 :     timeout->dbus_timeout = dbus_timeout;
     332             : 
     333           0 :     tv = _get_interval_tv(dbus_timeout_get_interval(dbus_timeout));
     334           0 :     timeout->te = tevent_add_timer(conn->ev, timeout, tv,
     335             :                                    sbus_timeout_handler, timeout);
     336           0 :     if (!timeout->te) {
     337           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Failed to set up timeout event!\n");
     338           0 :         return FALSE;
     339             :     }
     340             : 
     341             :     /* Save the event to the watch object so it can be removed later */
     342           0 :     dbus_timeout_set_data(timeout->dbus_timeout, timeout, NULL);
     343             : 
     344           0 :     return TRUE;
     345             : }
     346             : 
     347             : /*
     348             :  * sbus_toggle_timeout
     349             :  * Hook for D-BUS to toggle the enabled/disabled state of a mainloop
     350             :  * event
     351             :  */
     352           0 : void sbus_toggle_timeout(DBusTimeout *dbus_timeout, void *data)
     353             : {
     354           0 :     DEBUG(SSSDBG_TRACE_INTERNAL, "%p\n", dbus_timeout);
     355             : 
     356           0 :     if (dbus_timeout_get_enabled(dbus_timeout)) {
     357           0 :         sbus_add_timeout(dbus_timeout, data);
     358             :     } else {
     359           0 :         sbus_remove_timeout(dbus_timeout, data);
     360             :     }
     361           0 : }
     362             : 
     363             : /*
     364             :  * sbus_remove_timeout
     365             :  * Hook for D-BUS to remove time-based events from the mainloop
     366             :  */
     367           0 : void sbus_remove_timeout(DBusTimeout *dbus_timeout, void *data)
     368             : {
     369             :     void *timeout;
     370             : 
     371           0 :     DEBUG(SSSDBG_TRACE_INTERNAL, "%p\n", dbus_timeout);
     372             : 
     373           0 :     timeout = dbus_timeout_get_data(dbus_timeout);
     374             : 
     375             :     /* remove dbus timeout data */
     376           0 :     dbus_timeout_set_data(dbus_timeout, NULL, NULL);
     377             : 
     378             :     /* Freeing the event object will remove it from the event loop */
     379           0 :     talloc_free(timeout);
     380             : 
     381           0 : }

Generated by: LCOV version 1.10