LCOV - code coverage report
Current view: top level - src/libs/io/adapter/dbus - dbus.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 0 106 0.0 %
Date: 2019-09-12 12:28:41 Functions: 0 12 0.0 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  *
       4             :  * @brief I/O Adapter for D-Bus.
       5             :  *
       6             :  * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
       7             :  */
       8             : #include <kdbhelper.h>
       9             : #include <kdbio/adapters/dbus.h>
      10             : #include <kdblogger.h>
      11             : 
      12             : #include <stdlib.h>
      13             : #include <string.h>
      14             : 
      15             : 
      16             : typedef struct _ElektraIoAdapterDbusHandle
      17             : {
      18             :         DBusConnection * connection;
      19             :         ElektraIoInterface * ioBinding;
      20             :         ElektraIoIdleOperation * dispatchIdle;
      21             : } _ElektraIoAdapterDbusHandle;
      22             : 
      23             : typedef struct DbusAdapterWatchInfo
      24             : {
      25             :         _ElektraIoAdapterDbusHandle * private;
      26             :         DBusWatch * watch;
      27             : } DbusAdapterWatchInfo;
      28             : 
      29             : static int dbusToFlags (int dbus)
      30             : {
      31           0 :         int flags = 0;
      32           0 :         if (dbus & DBUS_WATCH_READABLE)
      33             :         {
      34           0 :                 flags |= ELEKTRA_IO_READABLE;
      35             :         }
      36           0 :         if (dbus & DBUS_WATCH_WRITABLE)
      37             :         {
      38           0 :                 flags |= ELEKTRA_IO_WRITABLE;
      39             :         }
      40             :         return flags;
      41             : }
      42             : 
      43           0 : static void dbusWrapperDispatch (ElektraIoIdleOperation * idle)
      44             : {
      45           0 :         _ElektraIoAdapterDbusHandle * priv = elektraIoIdleGetData (idle);
      46             : 
      47           0 :         if (dbus_connection_get_dispatch_status (priv->connection) == DBUS_DISPATCH_DATA_REMAINS)
      48             :         {
      49           0 :                 dbus_connection_dispatch (priv->connection);
      50             :         }
      51             :         // Disable idle if dispatching is done
      52           0 :         if (dbus_connection_get_dispatch_status (priv->connection) != DBUS_DISPATCH_DATA_REMAINS)
      53             :         {
      54           0 :                 elektraIoIdleSetEnabled (priv->dispatchIdle, 0);
      55           0 :                 elektraIoBindingUpdateIdle (priv->dispatchIdle);
      56             :         }
      57           0 : }
      58             : 
      59           0 : static void dbusWrapperHandleDispatch (DBusConnection * connection ELEKTRA_UNUSED, DBusDispatchStatus status, void * data)
      60             : {
      61           0 :         _ElektraIoAdapterDbusHandle * priv = (_ElektraIoAdapterDbusHandle *) data;
      62           0 :         if (status == DBUS_DISPATCH_DATA_REMAINS)
      63             :         {
      64           0 :                 elektraIoIdleSetEnabled (priv->dispatchIdle, 1);
      65           0 :                 elektraIoBindingUpdateIdle (priv->dispatchIdle);
      66             :         }
      67           0 : }
      68             : 
      69           0 : static void dbusWrapperPoll (ElektraIoFdOperation * fdOp, int flags)
      70             : {
      71           0 :         DbusAdapterWatchInfo * watchData = elektraIoFdGetData (fdOp);
      72           0 :         DBusWatch * watch = watchData->watch;
      73           0 :         _ElektraIoAdapterDbusHandle * priv = watchData->private;
      74             : 
      75           0 :         int dbus_condition = 0;
      76           0 :         if (flags & ELEKTRA_IO_READABLE)
      77             :         {
      78           0 :                 dbus_condition |= DBUS_WATCH_READABLE;
      79             :         }
      80           0 :         if (flags & ELEKTRA_IO_WRITABLE)
      81             :         {
      82           0 :                 dbus_condition |= DBUS_WATCH_WRITABLE;
      83             :         }
      84             : 
      85           0 :         dbus_watch_handle (watch, dbus_condition);
      86             : 
      87           0 :         dbusWrapperHandleDispatch (priv->connection, DBUS_DISPATCH_DATA_REMAINS, priv);
      88           0 : }
      89             : 
      90           0 : static void dbusWrapperTimeout (ElektraIoTimerOperation * timerOp)
      91             : {
      92           0 :         DBusTimeout * timeout = elektraIoTimerGetData (timerOp);
      93           0 :         dbus_timeout_handle (timeout);
      94           0 : }
      95             : 
      96           0 : static dbus_bool_t dbusWrapperAddWatch (DBusWatch * watch, void * data)
      97             : {
      98             :         // printf ("dbusWrapperAddWatch\n");
      99           0 :         _ElektraIoAdapterDbusHandle * private = (_ElektraIoAdapterDbusHandle *) data;
     100           0 :         ElektraIoInterface * ioBinding = private->ioBinding;
     101             : 
     102             :         // Get file descriptor from watch
     103           0 :         int fd = dbus_watch_get_unix_fd (watch);
     104           0 :         if (fd == -1)
     105             :         {
     106           0 :                 fd = dbus_watch_get_socket (watch);
     107             :         }
     108           0 :         if (fd == -1)
     109             :         {
     110             :                 ELEKTRA_LOG_WARNING ("Could not get file descriptor for watch");
     111             :                 return FALSE;
     112             :         }
     113             : 
     114           0 :         DbusAdapterWatchInfo * watchData = elektraMalloc (sizeof (*watchData));
     115           0 :         if (!watchData)
     116             :         {
     117             :                 return FALSE;
     118             :         }
     119           0 :         watchData->watch = watch;
     120           0 :         watchData->private = private;
     121             : 
     122             :         // Create new file descriptor info
     123           0 :         int flags = dbusToFlags (dbus_watch_get_flags (watch));
     124           0 :         int enabled = dbus_watch_get_enabled (watch);
     125           0 :         ElektraIoFdOperation * fdOp = elektraIoNewFdOperation (fd, flags, enabled, dbusWrapperPoll, watchData);
     126           0 :         if (!fdOp)
     127             :         {
     128             :                 return FALSE;
     129             :         }
     130             : 
     131             :         // Store file descriptor info in watcher
     132           0 :         dbus_watch_set_data (watch, (void *) fdOp, elektraFree);
     133             : 
     134           0 :         int success = elektraIoBindingAddFd (ioBinding, fdOp);
     135           0 :         if (!success)
     136             :         {
     137             :                 return FALSE;
     138             :         }
     139             : 
     140           0 :         return TRUE;
     141             : }
     142             : 
     143             : 
     144           0 : static void dbusWrapperRemoveWatch (DBusWatch * watch, void * data ELEKTRA_UNUSED)
     145             : {
     146           0 :         ElektraIoFdOperation * fdOp = dbus_watch_get_data (watch);
     147           0 :         DbusAdapterWatchInfo * watchInfo = elektraIoFdGetData (fdOp);
     148             : 
     149           0 :         elektraIoBindingRemoveFd (fdOp);
     150             : 
     151           0 :         elektraFree (watchInfo);
     152           0 : }
     153             : 
     154           0 : static void dbusWrapperWatchToggled (DBusWatch * watch, void * data ELEKTRA_UNUSED)
     155             : {
     156           0 :         ElektraIoFdOperation * fdOp = dbus_watch_get_data (watch);
     157             : 
     158           0 :         elektraIoFdSetEnabled (fdOp, dbus_watch_get_enabled (watch));
     159           0 :         elektraIoFdSetFlags (fdOp, dbusToFlags (dbus_watch_get_flags (watch)));
     160             : 
     161           0 :         elektraIoBindingUpdateFd (fdOp);
     162           0 : }
     163             : 
     164           0 : static dbus_bool_t dbusWrapperAddTimeout (DBusTimeout * timeout, void * data)
     165             : {
     166           0 :         _ElektraIoAdapterDbusHandle * private = (_ElektraIoAdapterDbusHandle *) data;
     167           0 :         ElektraIoInterface * ioBinding = private->ioBinding;
     168             : 
     169             :         // Create new file descriptor info
     170           0 :         int interval = dbus_timeout_get_interval (timeout);
     171           0 :         int enabled = dbus_timeout_get_enabled (timeout);
     172           0 :         ElektraIoTimerOperation * timerOp = elektraIoNewTimerOperation (interval, enabled, dbusWrapperTimeout, timeout);
     173           0 :         if (!timerOp)
     174             :         {
     175             :                 return FALSE;
     176             :         }
     177             : 
     178             :         // Store file descriptor info in timeouter
     179           0 :         dbus_timeout_set_data (timeout, (void *) timerOp, elektraFree);
     180             : 
     181           0 :         elektraIoBindingAddTimer (ioBinding, timerOp);
     182           0 :         return TRUE;
     183             : }
     184             : 
     185             : 
     186           0 : static void dbusWrapperRemoveTimeout (DBusTimeout * timeout, void * data ELEKTRA_UNUSED)
     187             : {
     188           0 :         ElektraIoTimerOperation * timerOp = dbus_timeout_get_data (timeout);
     189             : 
     190           0 :         elektraIoBindingRemoveTimer (timerOp);
     191           0 : }
     192             : 
     193           0 : static void dbusWrapperTimeoutToggled (DBusTimeout * timeout, void * data ELEKTRA_UNUSED)
     194             : {
     195           0 :         ElektraIoTimerOperation * timerOp = dbus_timeout_get_data (timeout);
     196             : 
     197           0 :         elektraIoTimerSetEnabled (timerOp, dbus_timeout_get_enabled (timeout));
     198           0 :         elektraIoTimerSetInterval (timerOp, dbus_timeout_get_interval (timeout));
     199             : 
     200           0 :         elektraIoBindingUpdateTimer (timerOp);
     201           0 : }
     202             : 
     203           0 : ElektraIoAdapterDbusHandle * elektraIoAdapterDbusAttach (DBusConnection * connection, ElektraIoInterface * ioBinding)
     204             : {
     205           0 :         _ElektraIoAdapterDbusHandle * priv = elektraMalloc (sizeof (*priv));
     206           0 :         if (!priv)
     207             :         {
     208             :                 return 0;
     209             :         }
     210           0 :         priv->connection = connection;
     211           0 :         priv->ioBinding = ioBinding;
     212             : 
     213           0 :         dbus_connection_set_watch_functions (connection, dbusWrapperAddWatch, dbusWrapperRemoveWatch, dbusWrapperWatchToggled, priv, NULL);
     214             : 
     215           0 :         dbus_connection_set_timeout_functions (connection, dbusWrapperAddTimeout, dbusWrapperRemoveTimeout, dbusWrapperTimeoutToggled, priv,
     216             :                                                NULL);
     217             : 
     218             :         // Add timeout for reading messages
     219           0 :         ElektraIoIdleOperation * dispatchIdle = elektraIoNewIdleOperation (0, dbusWrapperDispatch, priv);
     220           0 :         if (!dispatchIdle)
     221             :         {
     222             :                 return 0;
     223             :         }
     224           0 :         elektraIoBindingAddIdle (ioBinding, dispatchIdle);
     225             : 
     226           0 :         priv->dispatchIdle = dispatchIdle;
     227             : 
     228           0 :         dbus_connection_set_dispatch_status_function (connection, dbusWrapperHandleDispatch, priv, NULL);
     229             : 
     230           0 :         return priv;
     231             : }
     232             : 
     233             : // TODO rename to elektraIoAdapterDbusDetach when complete reversal is possible
     234           0 : int elektraIoAdapterDbusCleanup (ElektraIoAdapterDbusHandle * priv)
     235             : {
     236           0 :         DBusConnection * connection = priv->connection;
     237             : 
     238             :         // TODO currently not possible because dbus uses multiple watches for the same fd
     239             :         // which raises an assertion in uv when trying to remove one of them
     240             :         // calling dbus_connection_close() & dbus_connection_unref() works fine
     241             :         // dbus_connection_set_watch_functions (connection, NULL, NULL, NULL, NULL, NULL);
     242             :         // dbus_connection_set_timeout_functions (connection, NULL, NULL, NULL, NULL, NULL);
     243             : 
     244           0 :         dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
     245             : 
     246           0 :         elektraIoBindingRemoveIdle (priv->dispatchIdle);
     247           0 :         elektraFree (priv->dispatchIdle);
     248             : 
     249           0 :         elektraFree (priv);
     250             : 
     251           0 :         return 1;
     252             : }

Generated by: LCOV version 1.13