LCOV - code coverage report
Current view: top level - src/libs/io/adapter/zeromq - zeromq.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 50 75 66.7 %
Date: 2019-09-12 12:28:41 Functions: 4 6 66.7 %

          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 <kdbassert.h>
       9             : #include <kdbhelper.h>
      10             : #include <kdbio/adapters/zeromq.h>
      11             : #include <kdblogger.h>
      12             : 
      13             : #include <stdlib.h>
      14             : #include <string.h>
      15             : 
      16             : typedef struct _ElektraIoAdapterZeroMqHandle
      17             : {
      18             :         ElektraIoInterface * ioBinding;
      19             :         ElektraIoIdleOperation * dispatchIdle;
      20             :         ElektraIoFdOperation * fdOp;
      21             : 
      22             :         void * socket;
      23             : 
      24             :         ElektraIoAdapterZeroMqCallbackType type;
      25             :         ElektraIoAdapterZeroMqCallback callback;
      26             :         void * callbackContext;
      27             : 
      28             : } _ElektraIoAdapterZeroMqHandle;
      29             : 
      30           6 : static void zmqAdapterDispatch (_ElektraIoAdapterZeroMqHandle * handle)
      31             : {
      32           6 :         ElektraIoIdleOperation * dispatchIdle = handle->dispatchIdle;
      33             : 
      34             :         // Check if socket is readable or writable
      35           6 :         uint events = 0;
      36           6 :         size_t events_len = sizeof (events);
      37           6 :         zmq_getsockopt (handle->socket, ZMQ_EVENTS, &events, &events_len);
      38             : 
      39           6 :         if ((events & ZMQ_POLLIN) && handle->type == ELEKTRA_IO_ADAPTER_ZEROMQCB_READ)
      40             :         {
      41           2 :                 handle->callback (handle->socket, handle->callbackContext);
      42             :         }
      43           6 :         if ((events & ZMQ_POLLOUT) && handle->type == ELEKTRA_IO_ADAPTER_ZEROMQCB_WRITE)
      44             :         {
      45           0 :                 handle->callback (handle->socket, handle->callbackContext);
      46             :         }
      47             : 
      48           6 :         if (!(events & ZMQ_POLLIN) && !(events & ZMQ_POLLOUT))
      49             :         {
      50             :                 // Disable idle, nothing to do anymore
      51           4 :                 elektraIoIdleSetEnabled (dispatchIdle, 0);
      52           4 :                 elektraIoBindingUpdateIdle (dispatchIdle);
      53             :         }
      54           6 : }
      55             : 
      56           0 : static void zmqAdapterIdleCallback (ElektraIoIdleOperation * idleOp)
      57             : {
      58           0 :         _ElektraIoAdapterZeroMqHandle * handle = elektraIoIdleGetData (idleOp);
      59           0 :         ELEKTRA_NOT_NULL (handle);
      60           0 :         zmqAdapterDispatch (handle);
      61           0 : }
      62             : 
      63           6 : static void zmqAdapterFdCallback (ElektraIoFdOperation * fdOp, int flags)
      64             : {
      65           6 :         _ElektraIoAdapterZeroMqHandle * handle = elektraIoFdGetData (fdOp);
      66           6 :         ELEKTRA_NOT_NULL (handle);
      67           6 :         ElektraIoIdleOperation * dispatchIdle = handle->dispatchIdle;
      68             : 
      69           6 :         if (flags & ELEKTRA_IO_READABLE || flags & ELEKTRA_IO_WRITABLE)
      70             :         {
      71           6 :                 elektraIoIdleSetEnabled (dispatchIdle, 1);
      72           6 :                 elektraIoBindingUpdateIdle (dispatchIdle);
      73             :         }
      74             : 
      75             :         // Dispatch available data
      76           6 :         zmqAdapterDispatch (handle);
      77           6 : }
      78             : 
      79           4 : ElektraIoAdapterZeroMqHandle * elektraIoAdapterZeroMqAttach (void * socket, ElektraIoInterface * ioBinding,
      80             :                                                              ElektraIoAdapterZeroMqCallbackType type,
      81             :                                                              ElektraIoAdapterZeroMqCallback callback, void * context)
      82             : {
      83           4 :         if (socket == NULL)
      84             :         {
      85             :                 ELEKTRA_LOG_WARNING ("socket cannot be null");
      86             :                 return NULL;
      87             :         }
      88           4 :         if (ioBinding == NULL)
      89             :         {
      90             :                 ELEKTRA_LOG_WARNING ("ioBinding cannot be null");
      91             :                 return NULL;
      92             :         }
      93           4 :         if (callback == NULL)
      94             :         {
      95             :                 ELEKTRA_LOG_WARNING ("callback cannot be null");
      96             :                 return NULL;
      97             :         }
      98             : 
      99           4 :         _ElektraIoAdapterZeroMqHandle * handle = elektraMalloc (sizeof (*handle));
     100           4 :         if (!handle)
     101             :         {
     102             :                 return NULL;
     103             :         }
     104           4 :         handle->ioBinding = ioBinding;
     105           4 :         handle->socket = socket;
     106           4 :         handle->type = type;
     107           4 :         handle->callback = callback;
     108           4 :         handle->callbackContext = context;
     109             : 
     110             :         int fdOpFlags;
     111           4 :         switch (type)
     112             :         {
     113             :         case ELEKTRA_IO_ADAPTER_ZEROMQCB_READ:
     114             :                 fdOpFlags = ELEKTRA_IO_READABLE;
     115             :                 break;
     116             :         case ELEKTRA_IO_ADAPTER_ZEROMQCB_WRITE:
     117           0 :                 fdOpFlags = ELEKTRA_IO_WRITABLE;
     118           0 :                 break;
     119             :         default:
     120             :                 ELEKTRA_LOG_WARNING ("invalid callback type: %d", type);
     121             :                 return NULL;
     122             :                 break;
     123             :         }
     124             : 
     125             :         // Add sockets file descriptor to I/O binding
     126             :         int fd;
     127           4 :         size_t fd_len = sizeof (fd);
     128           4 :         if (zmq_getsockopt (socket, ZMQ_FD, &fd, &fd_len) != 0)
     129             :         {
     130             :                 ELEKTRA_LOG_WARNING ("zmq_getsockopt failed: could not get file descriptor from socket");
     131             :                 return NULL;
     132             :         }
     133           4 :         ElektraIoFdOperation * fdOp = elektraIoNewFdOperation (fd, fdOpFlags, 1, zmqAdapterFdCallback, handle);
     134           4 :         if (fdOp == NULL)
     135             :         {
     136           0 :                 elektraFree (handle);
     137           0 :                 return NULL;
     138             :         }
     139           4 :         handle->fdOp = fdOp;
     140           4 :         if (!elektraIoBindingAddFd (ioBinding, fdOp))
     141             :         {
     142           0 :                 elektraFree (fdOp);
     143           0 :                 elektraFree (handle);
     144           0 :                 return NULL;
     145             :         }
     146             : 
     147             :         // Add timeout for reading messages
     148           4 :         ElektraIoIdleOperation * dispatchIdle = elektraIoNewIdleOperation (0, zmqAdapterIdleCallback, handle);
     149           4 :         if (!dispatchIdle)
     150             :         {
     151           0 :                 elektraIoBindingRemoveFd (fdOp);
     152           0 :                 elektraFree (fdOp);
     153           0 :                 elektraFree (handle);
     154           0 :                 return NULL;
     155             :         }
     156           4 :         handle->dispatchIdle = dispatchIdle;
     157           4 :         if (!elektraIoBindingAddIdle (ioBinding, dispatchIdle))
     158             :         {
     159           0 :                 elektraFree (dispatchIdle);
     160           0 :                 elektraIoBindingRemoveFd (fdOp);
     161           0 :                 elektraFree (fdOp);
     162           0 :                 elektraFree (handle);
     163           0 :                 return NULL;
     164             :         }
     165             : 
     166             :         return handle;
     167             : }
     168             : 
     169           0 : void elektraIoAdapterZeroMqSetContext (ElektraIoAdapterZeroMqHandle * handle, void * context)
     170             : {
     171           0 :         handle->callbackContext = context;
     172           0 : }
     173             : 
     174           4 : int elektraIoAdapterZeroMqDetach (ElektraIoAdapterZeroMqHandle * handle)
     175             : {
     176             : 
     177           4 :         if (!elektraIoBindingRemoveIdle (handle->dispatchIdle))
     178             :         {
     179             :                 ELEKTRA_LOG_WARNING ("could not remove idle operation");
     180             :         }
     181           4 :         if (!elektraIoBindingRemoveFd (handle->fdOp))
     182             :         {
     183             :                 ELEKTRA_LOG_WARNING ("could not remove fd operation");
     184             :         }
     185           4 :         elektraFree (handle->dispatchIdle);
     186           4 :         elektraFree (handle->fdOp);
     187           4 :         elektraFree (handle);
     188             : 
     189           4 :         return 1;
     190             : }

Generated by: LCOV version 1.13