]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/libsystemd/sd-bus/bus-slot.c
Merge pull request #11827 from keszybz/pkgconfig-variables
[thirdparty/systemd.git] / src / libsystemd / sd-bus / bus-slot.c
index 8e9074c7dfb44e4d45690aa0f74a40a106aff869..f90a7f05ccf7fb0d9a94af914b3e62d0ba23c977 100644 (file)
@@ -1,21 +1,4 @@
-/***
-  This file is part of systemd.
-
-  Copyright 2013 Lennart Poettering
-
-  systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-
-  systemd is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
 
 #include "sd-bus.h"
 
@@ -54,18 +37,7 @@ sd_bus_slot *bus_slot_allocate(
         return slot;
 }
 
-_public_ sd_bus_slot* sd_bus_slot_ref(sd_bus_slot *slot) {
-
-        if (!slot)
-                return NULL;
-
-        assert(slot->n_ref > 0);
-
-        slot->n_ref++;
-        return slot;
-}
-
-void bus_slot_disconnect(sd_bus_slot *slot) {
+void bus_slot_disconnect(sd_bus_slot *slot, bool unref) {
         sd_bus *bus;
 
         assert(slot);
@@ -80,7 +52,7 @@ void bus_slot_disconnect(sd_bus_slot *slot) {
                 if (slot->reply_callback.cookie != 0)
                         ordered_hashmap_remove(slot->bus->reply_callbacks, &slot->reply_callback.cookie);
 
-                if (slot->reply_callback.timeout != 0)
+                if (slot->reply_callback.timeout_usec != 0)
                         prioq_remove(slot->bus->reply_callbacks_prioq, &slot->reply_callback, &slot->reply_callback.prioq_idx);
 
                 break;
@@ -93,12 +65,17 @@ void bus_slot_disconnect(sd_bus_slot *slot) {
         case BUS_MATCH_CALLBACK:
 
                 if (slot->match_added)
-                        bus_remove_match_internal(slot->bus, slot->match_callback.match_string, slot->match_callback.cookie);
+                        (void) bus_remove_match_internal(slot->bus, slot->match_callback.match_string);
+
+                if (slot->match_callback.install_slot) {
+                        bus_slot_disconnect(slot->match_callback.install_slot, true);
+                        slot->match_callback.install_slot = sd_bus_slot_unref(slot->match_callback.install_slot);
+                }
 
                 slot->bus->match_callbacks_modified = true;
                 bus_match_remove(&slot->bus->match_callbacks, &slot->match_callback);
 
-                free(slot->match_callback.match_string);
+                slot->match_callback.match_string = mfree(slot->match_callback.match_string);
 
                 break;
 
@@ -140,7 +117,7 @@ void bus_slot_disconnect(sd_bus_slot *slot) {
                 if (slot->node_vtable.node && slot->node_vtable.interface && slot->node_vtable.vtable) {
                         const sd_bus_vtable *v;
 
-                        for (v = slot->node_vtable.vtable; v->type != _SD_BUS_VTABLE_END; v++) {
+                        for (v = slot->node_vtable.vtable; v->type != _SD_BUS_VTABLE_END; v = bus_vtable_next(slot->node_vtable.vtable, v)) {
                                 struct vtable_member *x = NULL;
 
                                 switch (v->type) {
@@ -164,7 +141,6 @@ void bus_slot_disconnect(sd_bus_slot *slot) {
                                         key.interface = slot->node_vtable.interface;
                                         key.member = v->x.method.member;
 
-
                                         x = hashmap_remove(slot->bus->vtable_properties, &key);
                                         break;
                                 }}
@@ -173,7 +149,7 @@ void bus_slot_disconnect(sd_bus_slot *slot) {
                         }
                 }
 
-                free(slot->node_vtable.interface);
+                slot->node_vtable.interface = mfree(slot->node_vtable.interface);
 
                 if (slot->node_vtable.node) {
                         LIST_REMOVE(vtables, slot->node_vtable.node->vtables, &slot->node_vtable);
@@ -196,27 +172,24 @@ void bus_slot_disconnect(sd_bus_slot *slot) {
 
         if (!slot->floating)
                 sd_bus_unref(bus);
+        else if (unref)
+                sd_bus_slot_unref(slot);
 }
 
-_public_ sd_bus_slot* sd_bus_slot_unref(sd_bus_slot *slot) {
-
-        if (!slot)
-                return NULL;
+static sd_bus_slot* bus_slot_free(sd_bus_slot *slot) {
+        assert(slot);
 
-        assert(slot->n_ref > 0);
+        bus_slot_disconnect(slot, false);
 
-        if (slot->n_ref > 1) {
-                slot->n_ref--;
-                return NULL;
-        }
+        if (slot->destroy_callback)
+                slot->destroy_callback(slot->userdata);
 
-        bus_slot_disconnect(slot);
         free(slot->description);
-        free(slot);
-
-        return NULL;
+        return mfree(slot);
 }
 
+DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_bus_slot, sd_bus_slot, bus_slot_free);
+
 _public_ sd_bus* sd_bus_slot_get_bus(sd_bus_slot *slot) {
         assert_return(slot, NULL);
 
@@ -240,6 +213,22 @@ _public_ void *sd_bus_slot_set_userdata(sd_bus_slot *slot, void *userdata) {
         return ret;
 }
 
+_public_ int sd_bus_slot_set_destroy_callback(sd_bus_slot *slot, sd_bus_destroy_t callback) {
+        assert_return(slot, -EINVAL);
+
+        slot->destroy_callback = callback;
+        return 0;
+}
+
+_public_ int sd_bus_slot_get_destroy_callback(sd_bus_slot *slot, sd_bus_destroy_t *callback) {
+        assert_return(slot, -EINVAL);
+
+        if (callback)
+                *callback = slot->destroy_callback;
+
+        return !!slot->destroy_callback;
+}
+
 _public_ sd_bus_message *sd_bus_slot_get_current_message(sd_bus_slot *slot) {
         assert_return(slot, NULL);
         assert_return(slot->type >= 0, NULL);
@@ -270,6 +259,37 @@ _public_ void* sd_bus_slot_get_current_userdata(sd_bus_slot *slot) {
         return slot->bus->current_userdata;
 }
 
+_public_ int sd_bus_slot_get_floating(sd_bus_slot *slot) {
+        assert_return(slot, -EINVAL);
+
+        return slot->floating;
+}
+
+_public_ int sd_bus_slot_set_floating(sd_bus_slot *slot, int b) {
+        assert_return(slot, -EINVAL);
+
+        if (slot->floating == !!b)
+                return 0;
+
+        if (!slot->bus) /* already disconnected slots can't be reconnected */
+                return -ESTALE;
+
+        slot->floating = b;
+
+        /* When a slot is "floating" then the bus references the slot. Otherwise the slot references the bus. Hence,
+         * when we move from one to the other, let's increase one reference and decrease the other. */
+
+        if (b) {
+                sd_bus_slot_ref(slot);
+                sd_bus_unref(slot->bus);
+        } else {
+                sd_bus_ref(slot->bus);
+                sd_bus_slot_unref(slot);
+        }
+
+        return 1;
+}
+
 _public_ int sd_bus_slot_set_description(sd_bus_slot *slot, const char *description) {
         assert_return(slot, -EINVAL);
 
@@ -279,8 +299,13 @@ _public_ int sd_bus_slot_set_description(sd_bus_slot *slot, const char *descript
 _public_ int sd_bus_slot_get_description(sd_bus_slot *slot, const char **description) {
         assert_return(slot, -EINVAL);
         assert_return(description, -EINVAL);
-        assert_return(slot->description, -ENXIO);
 
-        *description = slot->description;
+        if (slot->description)
+                *description = slot->description;
+        else if (slot->type == BUS_MATCH_CALLBACK)
+                *description = slot->match_callback.match_string;
+        else
+                return -ENXIO;
+
         return 0;
 }