1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2013 Lennart Poettering
10 #include "alloc-util.h"
11 #include "bus-control.h"
12 #include "bus-objects.h"
14 #include "string-util.h"
16 sd_bus_slot
*bus_slot_allocate(
27 slot
= malloc0(offsetof(sd_bus_slot
, reply_callback
) + extra
);
34 slot
->floating
= floating
;
35 slot
->userdata
= userdata
;
40 LIST_PREPEND(slots
, bus
->slots
, slot
);
45 _public_ sd_bus_slot
* sd_bus_slot_ref(sd_bus_slot
*slot
) {
50 assert(slot
->n_ref
> 0);
56 void bus_slot_disconnect(sd_bus_slot
*slot
) {
66 case BUS_REPLY_CALLBACK
:
68 if (slot
->reply_callback
.cookie
!= 0)
69 ordered_hashmap_remove(slot
->bus
->reply_callbacks
, &slot
->reply_callback
.cookie
);
71 if (slot
->reply_callback
.timeout_usec
!= 0)
72 prioq_remove(slot
->bus
->reply_callbacks_prioq
, &slot
->reply_callback
, &slot
->reply_callback
.prioq_idx
);
76 case BUS_FILTER_CALLBACK
:
77 slot
->bus
->filter_callbacks_modified
= true;
78 LIST_REMOVE(callbacks
, slot
->bus
->filter_callbacks
, &slot
->filter_callback
);
81 case BUS_MATCH_CALLBACK
:
83 if (slot
->match_added
)
84 (void) bus_remove_match_internal(slot
->bus
, slot
->match_callback
.match_string
);
86 if (slot
->match_callback
.install_slot
) {
87 bus_slot_disconnect(slot
->match_callback
.install_slot
);
88 slot
->match_callback
.install_slot
= sd_bus_slot_unref(slot
->match_callback
.install_slot
);
91 slot
->bus
->match_callbacks_modified
= true;
92 bus_match_remove(&slot
->bus
->match_callbacks
, &slot
->match_callback
);
94 slot
->match_callback
.match_string
= mfree(slot
->match_callback
.match_string
);
98 case BUS_NODE_CALLBACK
:
100 if (slot
->node_callback
.node
) {
101 LIST_REMOVE(callbacks
, slot
->node_callback
.node
->callbacks
, &slot
->node_callback
);
102 slot
->bus
->nodes_modified
= true;
104 bus_node_gc(slot
->bus
, slot
->node_callback
.node
);
109 case BUS_NODE_ENUMERATOR
:
111 if (slot
->node_enumerator
.node
) {
112 LIST_REMOVE(enumerators
, slot
->node_enumerator
.node
->enumerators
, &slot
->node_enumerator
);
113 slot
->bus
->nodes_modified
= true;
115 bus_node_gc(slot
->bus
, slot
->node_enumerator
.node
);
120 case BUS_NODE_OBJECT_MANAGER
:
122 if (slot
->node_object_manager
.node
) {
123 LIST_REMOVE(object_managers
, slot
->node_object_manager
.node
->object_managers
, &slot
->node_object_manager
);
124 slot
->bus
->nodes_modified
= true;
126 bus_node_gc(slot
->bus
, slot
->node_object_manager
.node
);
131 case BUS_NODE_VTABLE
:
133 if (slot
->node_vtable
.node
&& slot
->node_vtable
.interface
&& slot
->node_vtable
.vtable
) {
134 const sd_bus_vtable
*v
;
136 for (v
= slot
->node_vtable
.vtable
; v
->type
!= _SD_BUS_VTABLE_END
; v
++) {
137 struct vtable_member
*x
= NULL
;
141 case _SD_BUS_VTABLE_METHOD
: {
142 struct vtable_member key
;
144 key
.path
= slot
->node_vtable
.node
->path
;
145 key
.interface
= slot
->node_vtable
.interface
;
146 key
.member
= v
->x
.method
.member
;
148 x
= hashmap_remove(slot
->bus
->vtable_methods
, &key
);
152 case _SD_BUS_VTABLE_PROPERTY
:
153 case _SD_BUS_VTABLE_WRITABLE_PROPERTY
: {
154 struct vtable_member key
;
156 key
.path
= slot
->node_vtable
.node
->path
;
157 key
.interface
= slot
->node_vtable
.interface
;
158 key
.member
= v
->x
.method
.member
;
160 x
= hashmap_remove(slot
->bus
->vtable_properties
, &key
);
168 slot
->node_vtable
.interface
= mfree(slot
->node_vtable
.interface
);
170 if (slot
->node_vtable
.node
) {
171 LIST_REMOVE(vtables
, slot
->node_vtable
.node
->vtables
, &slot
->node_vtable
);
172 slot
->bus
->nodes_modified
= true;
174 bus_node_gc(slot
->bus
, slot
->node_vtable
.node
);
180 assert_not_reached("Wut? Unknown slot type?");
185 slot
->type
= _BUS_SLOT_INVALID
;
187 LIST_REMOVE(slots
, bus
->slots
, slot
);
193 _public_ sd_bus_slot
* sd_bus_slot_unref(sd_bus_slot
*slot
) {
198 assert(slot
->n_ref
> 0);
200 if (slot
->n_ref
> 1) {
205 bus_slot_disconnect(slot
);
207 if (slot
->destroy_callback
)
208 slot
->destroy_callback(slot
->userdata
);
210 free(slot
->description
);
214 _public_ sd_bus
* sd_bus_slot_get_bus(sd_bus_slot
*slot
) {
215 assert_return(slot
, NULL
);
220 _public_
void *sd_bus_slot_get_userdata(sd_bus_slot
*slot
) {
221 assert_return(slot
, NULL
);
223 return slot
->userdata
;
226 _public_
void *sd_bus_slot_set_userdata(sd_bus_slot
*slot
, void *userdata
) {
229 assert_return(slot
, NULL
);
231 ret
= slot
->userdata
;
232 slot
->userdata
= userdata
;
237 _public_
int sd_bus_slot_set_destroy_callback(sd_bus_slot
*slot
, sd_bus_destroy_t callback
) {
238 assert_return(slot
, -EINVAL
);
240 slot
->destroy_callback
= callback
;
244 _public_
int sd_bus_slot_get_destroy_callback(sd_bus_slot
*slot
, sd_bus_destroy_t
*callback
) {
245 assert_return(slot
, -EINVAL
);
248 *callback
= slot
->destroy_callback
;
250 return !!slot
->destroy_callback
;
253 _public_ sd_bus_message
*sd_bus_slot_get_current_message(sd_bus_slot
*slot
) {
254 assert_return(slot
, NULL
);
255 assert_return(slot
->type
>= 0, NULL
);
257 if (slot
->bus
->current_slot
!= slot
)
260 return slot
->bus
->current_message
;
263 _public_ sd_bus_message_handler_t
sd_bus_slot_get_current_handler(sd_bus_slot
*slot
) {
264 assert_return(slot
, NULL
);
265 assert_return(slot
->type
>= 0, NULL
);
267 if (slot
->bus
->current_slot
!= slot
)
270 return slot
->bus
->current_handler
;
273 _public_
void* sd_bus_slot_get_current_userdata(sd_bus_slot
*slot
) {
274 assert_return(slot
, NULL
);
275 assert_return(slot
->type
>= 0, NULL
);
277 if (slot
->bus
->current_slot
!= slot
)
280 return slot
->bus
->current_userdata
;
283 _public_
int sd_bus_slot_get_floating(sd_bus_slot
*slot
) {
284 assert_return(slot
, -EINVAL
);
286 return slot
->floating
;
289 _public_
int sd_bus_slot_set_floating(sd_bus_slot
*slot
, int b
) {
290 assert_return(slot
, -EINVAL
);
292 if (slot
->floating
== !!b
)
295 if (!slot
->bus
) /* already disconnected slots can't be reconnected */
300 /* When a slot is "floating" then the bus references the slot. Otherwise the slot references the bus. Hence,
301 * when we move from one to the other, let's increase one reference and decrease the other. */
304 sd_bus_slot_ref(slot
);
305 sd_bus_unref(slot
->bus
);
307 sd_bus_ref(slot
->bus
);
308 sd_bus_slot_unref(slot
);
314 _public_
int sd_bus_slot_set_description(sd_bus_slot
*slot
, const char *description
) {
315 assert_return(slot
, -EINVAL
);
317 return free_and_strdup(&slot
->description
, description
);
320 _public_
int sd_bus_slot_get_description(sd_bus_slot
*slot
, const char **description
) {
321 assert_return(slot
, -EINVAL
);
322 assert_return(description
, -EINVAL
);
324 if (slot
->description
)
325 *description
= slot
->description
;
326 else if (slot
->type
== BUS_MATCH_CALLBACK
)
327 *description
= slot
->match_callback
.match_string
;