1 /* SPDX-License-Identifier: LGPL-2.1+ */
5 #include "alloc-util.h"
6 #include "bus-control.h"
7 #include "bus-objects.h"
9 #include "string-util.h"
11 sd_bus_slot
*bus_slot_allocate(
22 slot
= malloc0(offsetof(sd_bus_slot
, reply_callback
) + extra
);
29 slot
->floating
= floating
;
30 slot
->userdata
= userdata
;
35 LIST_PREPEND(slots
, bus
->slots
, slot
);
40 void bus_slot_disconnect(sd_bus_slot
*slot
, bool unref
) {
50 case BUS_REPLY_CALLBACK
:
52 if (slot
->reply_callback
.cookie
!= 0)
53 ordered_hashmap_remove(slot
->bus
->reply_callbacks
, &slot
->reply_callback
.cookie
);
55 if (slot
->reply_callback
.timeout_usec
!= 0)
56 prioq_remove(slot
->bus
->reply_callbacks_prioq
, &slot
->reply_callback
, &slot
->reply_callback
.prioq_idx
);
60 case BUS_FILTER_CALLBACK
:
61 slot
->bus
->filter_callbacks_modified
= true;
62 LIST_REMOVE(callbacks
, slot
->bus
->filter_callbacks
, &slot
->filter_callback
);
65 case BUS_MATCH_CALLBACK
:
67 if (slot
->match_added
)
68 (void) bus_remove_match_internal(slot
->bus
, slot
->match_callback
.match_string
);
70 if (slot
->match_callback
.install_slot
) {
71 bus_slot_disconnect(slot
->match_callback
.install_slot
, true);
72 slot
->match_callback
.install_slot
= sd_bus_slot_unref(slot
->match_callback
.install_slot
);
75 slot
->bus
->match_callbacks_modified
= true;
76 bus_match_remove(&slot
->bus
->match_callbacks
, &slot
->match_callback
);
78 slot
->match_callback
.match_string
= mfree(slot
->match_callback
.match_string
);
82 case BUS_NODE_CALLBACK
:
84 if (slot
->node_callback
.node
) {
85 LIST_REMOVE(callbacks
, slot
->node_callback
.node
->callbacks
, &slot
->node_callback
);
86 slot
->bus
->nodes_modified
= true;
88 bus_node_gc(slot
->bus
, slot
->node_callback
.node
);
93 case BUS_NODE_ENUMERATOR
:
95 if (slot
->node_enumerator
.node
) {
96 LIST_REMOVE(enumerators
, slot
->node_enumerator
.node
->enumerators
, &slot
->node_enumerator
);
97 slot
->bus
->nodes_modified
= true;
99 bus_node_gc(slot
->bus
, slot
->node_enumerator
.node
);
104 case BUS_NODE_OBJECT_MANAGER
:
106 if (slot
->node_object_manager
.node
) {
107 LIST_REMOVE(object_managers
, slot
->node_object_manager
.node
->object_managers
, &slot
->node_object_manager
);
108 slot
->bus
->nodes_modified
= true;
110 bus_node_gc(slot
->bus
, slot
->node_object_manager
.node
);
115 case BUS_NODE_VTABLE
:
117 if (slot
->node_vtable
.node
&& slot
->node_vtable
.interface
&& slot
->node_vtable
.vtable
) {
118 const sd_bus_vtable
*v
;
120 for (v
= slot
->node_vtable
.vtable
; v
->type
!= _SD_BUS_VTABLE_END
; v
= bus_vtable_next(slot
->node_vtable
.vtable
, v
)) {
121 struct vtable_member
*x
= NULL
;
125 case _SD_BUS_VTABLE_METHOD
: {
126 struct vtable_member key
;
128 key
.path
= slot
->node_vtable
.node
->path
;
129 key
.interface
= slot
->node_vtable
.interface
;
130 key
.member
= v
->x
.method
.member
;
132 x
= hashmap_remove(slot
->bus
->vtable_methods
, &key
);
136 case _SD_BUS_VTABLE_PROPERTY
:
137 case _SD_BUS_VTABLE_WRITABLE_PROPERTY
: {
138 struct vtable_member key
;
140 key
.path
= slot
->node_vtable
.node
->path
;
141 key
.interface
= slot
->node_vtable
.interface
;
142 key
.member
= v
->x
.method
.member
;
144 x
= hashmap_remove(slot
->bus
->vtable_properties
, &key
);
152 slot
->node_vtable
.interface
= mfree(slot
->node_vtable
.interface
);
154 if (slot
->node_vtable
.node
) {
155 LIST_REMOVE(vtables
, slot
->node_vtable
.node
->vtables
, &slot
->node_vtable
);
156 slot
->bus
->nodes_modified
= true;
158 bus_node_gc(slot
->bus
, slot
->node_vtable
.node
);
164 assert_not_reached("Wut? Unknown slot type?");
169 slot
->type
= _BUS_SLOT_INVALID
;
171 LIST_REMOVE(slots
, bus
->slots
, slot
);
176 sd_bus_slot_unref(slot
);
179 static sd_bus_slot
* bus_slot_free(sd_bus_slot
*slot
) {
182 bus_slot_disconnect(slot
, false);
184 if (slot
->destroy_callback
)
185 slot
->destroy_callback(slot
->userdata
);
187 free(slot
->description
);
191 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_bus_slot
, sd_bus_slot
, bus_slot_free
);
193 _public_ sd_bus
* sd_bus_slot_get_bus(sd_bus_slot
*slot
) {
194 assert_return(slot
, NULL
);
199 _public_
void *sd_bus_slot_get_userdata(sd_bus_slot
*slot
) {
200 assert_return(slot
, NULL
);
202 return slot
->userdata
;
205 _public_
void *sd_bus_slot_set_userdata(sd_bus_slot
*slot
, void *userdata
) {
208 assert_return(slot
, NULL
);
210 ret
= slot
->userdata
;
211 slot
->userdata
= userdata
;
216 _public_
int sd_bus_slot_set_destroy_callback(sd_bus_slot
*slot
, sd_bus_destroy_t callback
) {
217 assert_return(slot
, -EINVAL
);
219 slot
->destroy_callback
= callback
;
223 _public_
int sd_bus_slot_get_destroy_callback(sd_bus_slot
*slot
, sd_bus_destroy_t
*callback
) {
224 assert_return(slot
, -EINVAL
);
227 *callback
= slot
->destroy_callback
;
229 return !!slot
->destroy_callback
;
232 _public_ sd_bus_message
*sd_bus_slot_get_current_message(sd_bus_slot
*slot
) {
233 assert_return(slot
, NULL
);
234 assert_return(slot
->type
>= 0, NULL
);
236 if (slot
->bus
->current_slot
!= slot
)
239 return slot
->bus
->current_message
;
242 _public_ sd_bus_message_handler_t
sd_bus_slot_get_current_handler(sd_bus_slot
*slot
) {
243 assert_return(slot
, NULL
);
244 assert_return(slot
->type
>= 0, NULL
);
246 if (slot
->bus
->current_slot
!= slot
)
249 return slot
->bus
->current_handler
;
252 _public_
void* sd_bus_slot_get_current_userdata(sd_bus_slot
*slot
) {
253 assert_return(slot
, NULL
);
254 assert_return(slot
->type
>= 0, NULL
);
256 if (slot
->bus
->current_slot
!= slot
)
259 return slot
->bus
->current_userdata
;
262 _public_
int sd_bus_slot_get_floating(sd_bus_slot
*slot
) {
263 assert_return(slot
, -EINVAL
);
265 return slot
->floating
;
268 _public_
int sd_bus_slot_set_floating(sd_bus_slot
*slot
, int b
) {
269 assert_return(slot
, -EINVAL
);
271 if (slot
->floating
== !!b
)
274 if (!slot
->bus
) /* already disconnected slots can't be reconnected */
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. */
283 sd_bus_slot_ref(slot
);
284 sd_bus_unref(slot
->bus
);
286 sd_bus_ref(slot
->bus
);
287 sd_bus_slot_unref(slot
);
293 _public_
int sd_bus_slot_set_description(sd_bus_slot
*slot
, const char *description
) {
294 assert_return(slot
, -EINVAL
);
296 return free_and_strdup(&slot
->description
, description
);
299 _public_
int sd_bus_slot_get_description(sd_bus_slot
*slot
, const char **description
) {
300 assert_return(slot
, -EINVAL
);
301 assert_return(description
, -EINVAL
);
303 if (slot
->description
)
304 *description
= slot
->description
;
305 else if (slot
->type
== BUS_MATCH_CALLBACK
)
306 *description
= slot
->match_callback
.match_string
;