LCOV - code coverage report
Current view: top level - libsystemd/sd-bus - bus-slot.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 110 165 66.7 %
Date: 2019-08-22 15:41:25 Functions: 8 17 47.1 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include "sd-bus.h"
       4             : 
       5             : #include "alloc-util.h"
       6             : #include "bus-control.h"
       7             : #include "bus-objects.h"
       8             : #include "bus-slot.h"
       9             : #include "string-util.h"
      10             : 
      11          92 : sd_bus_slot *bus_slot_allocate(
      12             :                 sd_bus *bus,
      13             :                 bool floating,
      14             :                 BusSlotType type,
      15             :                 size_t extra,
      16             :                 void *userdata) {
      17             : 
      18             :         sd_bus_slot *slot;
      19             : 
      20          92 :         assert(bus);
      21             : 
      22          92 :         slot = malloc0(offsetof(sd_bus_slot, reply_callback) + extra);
      23          92 :         if (!slot)
      24           0 :                 return NULL;
      25             : 
      26          92 :         slot->n_ref = 1;
      27          92 :         slot->type = type;
      28          92 :         slot->bus = bus;
      29          92 :         slot->floating = floating;
      30          92 :         slot->userdata = userdata;
      31             : 
      32          92 :         if (!floating)
      33          18 :                 sd_bus_ref(bus);
      34             : 
      35          92 :         LIST_PREPEND(slots, bus->slots, slot);
      36             : 
      37          92 :         return slot;
      38             : }
      39             : 
      40         193 : void bus_slot_disconnect(sd_bus_slot *slot, bool unref) {
      41             :         sd_bus *bus;
      42             : 
      43         193 :         assert(slot);
      44             : 
      45         193 :         if (!slot->bus)
      46         101 :                 return;
      47             : 
      48          92 :         switch (slot->type) {
      49             : 
      50          45 :         case BUS_REPLY_CALLBACK:
      51             : 
      52          45 :                 if (slot->reply_callback.cookie != 0)
      53          16 :                         ordered_hashmap_remove(slot->bus->reply_callbacks, &slot->reply_callback.cookie);
      54             : 
      55          45 :                 if (slot->reply_callback.timeout_usec != 0)
      56          16 :                         prioq_remove(slot->bus->reply_callbacks_prioq, &slot->reply_callback, &slot->reply_callback.prioq_idx);
      57             : 
      58          45 :                 break;
      59             : 
      60           0 :         case BUS_FILTER_CALLBACK:
      61           0 :                 slot->bus->filter_callbacks_modified = true;
      62           0 :                 LIST_REMOVE(callbacks, slot->bus->filter_callbacks, &slot->filter_callback);
      63           0 :                 break;
      64             : 
      65          30 :         case BUS_MATCH_CALLBACK:
      66             : 
      67          30 :                 if (slot->match_added)
      68          17 :                         (void) bus_remove_match_internal(slot->bus, slot->match_callback.match_string);
      69             : 
      70          30 :                 if (slot->match_callback.install_slot) {
      71          12 :                         bus_slot_disconnect(slot->match_callback.install_slot, true);
      72          12 :                         slot->match_callback.install_slot = sd_bus_slot_unref(slot->match_callback.install_slot);
      73             :                 }
      74             : 
      75          30 :                 slot->bus->match_callbacks_modified = true;
      76          30 :                 bus_match_remove(&slot->bus->match_callbacks, &slot->match_callback);
      77             : 
      78          30 :                 slot->match_callback.match_string = mfree(slot->match_callback.match_string);
      79             : 
      80          30 :                 break;
      81             : 
      82           1 :         case BUS_NODE_CALLBACK:
      83             : 
      84           1 :                 if (slot->node_callback.node) {
      85           1 :                         LIST_REMOVE(callbacks, slot->node_callback.node->callbacks, &slot->node_callback);
      86           1 :                         slot->bus->nodes_modified = true;
      87             : 
      88           1 :                         bus_node_gc(slot->bus, slot->node_callback.node);
      89             :                 }
      90             : 
      91           1 :                 break;
      92             : 
      93           2 :         case BUS_NODE_ENUMERATOR:
      94             : 
      95           2 :                 if (slot->node_enumerator.node) {
      96           2 :                         LIST_REMOVE(enumerators, slot->node_enumerator.node->enumerators, &slot->node_enumerator);
      97           2 :                         slot->bus->nodes_modified = true;
      98             : 
      99           2 :                         bus_node_gc(slot->bus, slot->node_enumerator.node);
     100             :                 }
     101             : 
     102           2 :                 break;
     103             : 
     104           2 :         case BUS_NODE_OBJECT_MANAGER:
     105             : 
     106           2 :                 if (slot->node_object_manager.node) {
     107           2 :                         LIST_REMOVE(object_managers, slot->node_object_manager.node->object_managers, &slot->node_object_manager);
     108           2 :                         slot->bus->nodes_modified = true;
     109             : 
     110           2 :                         bus_node_gc(slot->bus, slot->node_object_manager.node);
     111             :                 }
     112             : 
     113           2 :                 break;
     114             : 
     115          12 :         case BUS_NODE_VTABLE:
     116             : 
     117          12 :                 if (slot->node_vtable.node && slot->node_vtable.interface && slot->node_vtable.vtable) {
     118             :                         const sd_bus_vtable *v;
     119             : 
     120         131 :                         for (v = slot->node_vtable.vtable; v->type != _SD_BUS_VTABLE_END; v = bus_vtable_next(slot->node_vtable.vtable, v)) {
     121         119 :                                 struct vtable_member *x = NULL;
     122             : 
     123         119 :                                 switch (v->type) {
     124             : 
     125          52 :                                 case _SD_BUS_VTABLE_METHOD: {
     126             :                                         struct vtable_member key;
     127             : 
     128          52 :                                         key.path = slot->node_vtable.node->path;
     129          52 :                                         key.interface = slot->node_vtable.interface;
     130          52 :                                         key.member = v->x.method.member;
     131             : 
     132          52 :                                         x = hashmap_remove(slot->bus->vtable_methods, &key);
     133          52 :                                         break;
     134             :                                 }
     135             : 
     136          43 :                                 case _SD_BUS_VTABLE_PROPERTY:
     137             :                                 case _SD_BUS_VTABLE_WRITABLE_PROPERTY: {
     138             :                                         struct vtable_member key;
     139             : 
     140          43 :                                         key.path = slot->node_vtable.node->path;
     141          43 :                                         key.interface = slot->node_vtable.interface;
     142          43 :                                         key.member = v->x.method.member;
     143             : 
     144          43 :                                         x = hashmap_remove(slot->bus->vtable_properties, &key);
     145          43 :                                         break;
     146             :                                 }}
     147             : 
     148         119 :                                 free(x);
     149             :                         }
     150             :                 }
     151             : 
     152          12 :                 slot->node_vtable.interface = mfree(slot->node_vtable.interface);
     153             : 
     154          12 :                 if (slot->node_vtable.node) {
     155          12 :                         LIST_REMOVE(vtables, slot->node_vtable.node->vtables, &slot->node_vtable);
     156          12 :                         slot->bus->nodes_modified = true;
     157             : 
     158          12 :                         bus_node_gc(slot->bus, slot->node_vtable.node);
     159             :                 }
     160             : 
     161          12 :                 break;
     162             : 
     163           0 :         default:
     164           0 :                 assert_not_reached("Wut? Unknown slot type?");
     165             :         }
     166             : 
     167          92 :         bus = slot->bus;
     168             : 
     169          92 :         slot->type = _BUS_SLOT_INVALID;
     170          92 :         slot->bus = NULL;
     171          92 :         LIST_REMOVE(slots, bus->slots, slot);
     172             : 
     173          92 :         if (!slot->floating)
     174           3 :                 sd_bus_unref(bus);
     175          89 :         else if (unref)
     176          89 :                 sd_bus_slot_unref(slot);
     177             : }
     178             : 
     179          92 : static sd_bus_slot* bus_slot_free(sd_bus_slot *slot) {
     180          92 :         assert(slot);
     181             : 
     182          92 :         bus_slot_disconnect(slot, false);
     183             : 
     184          92 :         if (slot->destroy_callback)
     185           1 :                 slot->destroy_callback(slot->userdata);
     186             : 
     187          92 :         free(slot->description);
     188          92 :         return mfree(slot);
     189             : }
     190             : 
     191        2500 : DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_bus_slot, sd_bus_slot, bus_slot_free);
     192             : 
     193           0 : _public_ sd_bus* sd_bus_slot_get_bus(sd_bus_slot *slot) {
     194           0 :         assert_return(slot, NULL);
     195             : 
     196           0 :         return slot->bus;
     197             : }
     198             : 
     199           0 : _public_ void *sd_bus_slot_get_userdata(sd_bus_slot *slot) {
     200           0 :         assert_return(slot, NULL);
     201             : 
     202           0 :         return slot->userdata;
     203             : }
     204             : 
     205           0 : _public_ void *sd_bus_slot_set_userdata(sd_bus_slot *slot, void *userdata) {
     206             :         void *ret;
     207             : 
     208           0 :         assert_return(slot, NULL);
     209             : 
     210           0 :         ret = slot->userdata;
     211           0 :         slot->userdata = userdata;
     212             : 
     213           0 :         return ret;
     214             : }
     215             : 
     216           1 : _public_ int sd_bus_slot_set_destroy_callback(sd_bus_slot *slot, sd_bus_destroy_t callback) {
     217           1 :         assert_return(slot, -EINVAL);
     218             : 
     219           1 :         slot->destroy_callback = callback;
     220           1 :         return 0;
     221             : }
     222             : 
     223           4 : _public_ int sd_bus_slot_get_destroy_callback(sd_bus_slot *slot, sd_bus_destroy_t *callback) {
     224           4 :         assert_return(slot, -EINVAL);
     225             : 
     226           4 :         if (callback)
     227           2 :                 *callback = slot->destroy_callback;
     228             : 
     229           4 :         return !!slot->destroy_callback;
     230             : }
     231             : 
     232           0 : _public_ sd_bus_message *sd_bus_slot_get_current_message(sd_bus_slot *slot) {
     233           0 :         assert_return(slot, NULL);
     234           0 :         assert_return(slot->type >= 0, NULL);
     235             : 
     236           0 :         if (slot->bus->current_slot != slot)
     237           0 :                 return NULL;
     238             : 
     239           0 :         return slot->bus->current_message;
     240             : }
     241             : 
     242           0 : _public_ sd_bus_message_handler_t sd_bus_slot_get_current_handler(sd_bus_slot *slot) {
     243           0 :         assert_return(slot, NULL);
     244           0 :         assert_return(slot->type >= 0, NULL);
     245             : 
     246           0 :         if (slot->bus->current_slot != slot)
     247           0 :                 return NULL;
     248             : 
     249           0 :         return slot->bus->current_handler;
     250             : }
     251             : 
     252           0 : _public_ void* sd_bus_slot_get_current_userdata(sd_bus_slot *slot) {
     253           0 :         assert_return(slot, NULL);
     254           0 :         assert_return(slot->type >= 0, NULL);
     255             : 
     256           0 :         if (slot->bus->current_slot != slot)
     257           0 :                 return NULL;
     258             : 
     259           0 :         return slot->bus->current_userdata;
     260             : }
     261             : 
     262           0 : _public_ int sd_bus_slot_get_floating(sd_bus_slot *slot) {
     263           0 :         assert_return(slot, -EINVAL);
     264             : 
     265           0 :         return slot->floating;
     266             : }
     267             : 
     268          15 : _public_ int sd_bus_slot_set_floating(sd_bus_slot *slot, int b) {
     269          15 :         assert_return(slot, -EINVAL);
     270             : 
     271          15 :         if (slot->floating == !!b)
     272           0 :                 return 0;
     273             : 
     274          15 :         if (!slot->bus) /* already disconnected slots can't be reconnected */
     275           0 :                 return -ESTALE;
     276             : 
     277          15 :         slot->floating = b;
     278             : 
     279             :         /* When a slot is "floating" then the bus references the slot. Otherwise the slot references the bus. Hence,
     280             :          * when we move from one to the other, let's increase one reference and decrease the other. */
     281             : 
     282          15 :         if (b) {
     283          15 :                 sd_bus_slot_ref(slot);
     284          15 :                 sd_bus_unref(slot->bus);
     285             :         } else {
     286           0 :                 sd_bus_ref(slot->bus);
     287           0 :                 sd_bus_slot_unref(slot);
     288             :         }
     289             : 
     290          15 :         return 1;
     291             : }
     292             : 
     293           0 : _public_ int sd_bus_slot_set_description(sd_bus_slot *slot, const char *description) {
     294           0 :         assert_return(slot, -EINVAL);
     295             : 
     296           0 :         return free_and_strdup(&slot->description, description);
     297             : }
     298             : 
     299           0 : _public_ int sd_bus_slot_get_description(sd_bus_slot *slot, const char **description) {
     300           0 :         assert_return(slot, -EINVAL);
     301           0 :         assert_return(description, -EINVAL);
     302             : 
     303           0 :         if (slot->description)
     304           0 :                 *description = slot->description;
     305           0 :         else if (slot->type == BUS_MATCH_CALLBACK)
     306           0 :                 *description = slot->match_callback.match_string;
     307             :         else
     308           0 :                 return -ENXIO;
     309             : 
     310           0 :         return 0;
     311             : }

Generated by: LCOV version 1.14