1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright 2013 Lennart Poettering
8 #include "alloc-util.h"
9 #include "bus-control.h"
10 #include "bus-objects.h"
12 #include "string-util.h"
14 sd_bus_slot
*bus_slot_allocate(
25 slot
= malloc0(offsetof(sd_bus_slot
, reply_callback
) + extra
);
32 slot
->floating
= floating
;
33 slot
->userdata
= userdata
;
38 LIST_PREPEND(slots
, bus
->slots
, slot
);
43 _public_ sd_bus_slot
* sd_bus_slot_ref(sd_bus_slot
*slot
) {
48 assert(slot
->n_ref
> 0);
54 void bus_slot_disconnect(sd_bus_slot
*slot
) {
64 case BUS_REPLY_CALLBACK
:
66 if (slot
->reply_callback
.cookie
!= 0)
67 ordered_hashmap_remove(slot
->bus
->reply_callbacks
, &slot
->reply_callback
.cookie
);
69 if (slot
->reply_callback
.timeout_usec
!= 0)
70 prioq_remove(slot
->bus
->reply_callbacks_prioq
, &slot
->reply_callback
, &slot
->reply_callback
.prioq_idx
);
74 case BUS_FILTER_CALLBACK
:
75 slot
->bus
->filter_callbacks_modified
= true;
76 LIST_REMOVE(callbacks
, slot
->bus
->filter_callbacks
, &slot
->filter_callback
);
79 case BUS_MATCH_CALLBACK
:
81 if (slot
->match_added
)
82 (void) bus_remove_match_internal(slot
->bus
, slot
->match_callback
.match_string
);
84 if (slot
->match_callback
.install_slot
) {
85 bus_slot_disconnect(slot
->match_callback
.install_slot
);
86 slot
->match_callback
.install_slot
= sd_bus_slot_unref(slot
->match_callback
.install_slot
);
89 slot
->bus
->match_callbacks_modified
= true;
90 bus_match_remove(&slot
->bus
->match_callbacks
, &slot
->match_callback
);
92 slot
->match_callback
.match_string
= mfree(slot
->match_callback
.match_string
);
96 case BUS_NODE_CALLBACK
:
98 if (slot
->node_callback
.node
) {
99 LIST_REMOVE(callbacks
, slot
->node_callback
.node
->callbacks
, &slot
->node_callback
);
100 slot
->bus
->nodes_modified
= true;
102 bus_node_gc(slot
->bus
, slot
->node_callback
.node
);
107 case BUS_NODE_ENUMERATOR
:
109 if (slot
->node_enumerator
.node
) {
110 LIST_REMOVE(enumerators
, slot
->node_enumerator
.node
->enumerators
, &slot
->node_enumerator
);
111 slot
->bus
->nodes_modified
= true;
113 bus_node_gc(slot
->bus
, slot
->node_enumerator
.node
);
118 case BUS_NODE_OBJECT_MANAGER
:
120 if (slot
->node_object_manager
.node
) {
121 LIST_REMOVE(object_managers
, slot
->node_object_manager
.node
->object_managers
, &slot
->node_object_manager
);
122 slot
->bus
->nodes_modified
= true;
124 bus_node_gc(slot
->bus
, slot
->node_object_manager
.node
);
129 case BUS_NODE_VTABLE
:
131 if (slot
->node_vtable
.node
&& slot
->node_vtable
.interface
&& slot
->node_vtable
.vtable
) {
132 const sd_bus_vtable
*v
;
134 for (v
= slot
->node_vtable
.vtable
; v
->type
!= _SD_BUS_VTABLE_END
; v
++) {
135 struct vtable_member
*x
= NULL
;
139 case _SD_BUS_VTABLE_METHOD
: {
140 struct vtable_member key
;
142 key
.path
= slot
->node_vtable
.node
->path
;
143 key
.interface
= slot
->node_vtable
.interface
;
144 key
.member
= v
->x
.method
.member
;
146 x
= hashmap_remove(slot
->bus
->vtable_methods
, &key
);
150 case _SD_BUS_VTABLE_PROPERTY
:
151 case _SD_BUS_VTABLE_WRITABLE_PROPERTY
: {
152 struct vtable_member key
;
154 key
.path
= slot
->node_vtable
.node
->path
;
155 key
.interface
= slot
->node_vtable
.interface
;
156 key
.member
= v
->x
.method
.member
;
158 x
= hashmap_remove(slot
->bus
->vtable_properties
, &key
);
166 slot
->node_vtable
.interface
= mfree(slot
->node_vtable
.interface
);
168 if (slot
->node_vtable
.node
) {
169 LIST_REMOVE(vtables
, slot
->node_vtable
.node
->vtables
, &slot
->node_vtable
);
170 slot
->bus
->nodes_modified
= true;
172 bus_node_gc(slot
->bus
, slot
->node_vtable
.node
);
178 assert_not_reached("Wut? Unknown slot type?");
183 slot
->type
= _BUS_SLOT_INVALID
;
185 LIST_REMOVE(slots
, bus
->slots
, slot
);
191 _public_ sd_bus_slot
* sd_bus_slot_unref(sd_bus_slot
*slot
) {
196 assert(slot
->n_ref
> 0);
198 if (slot
->n_ref
> 1) {
203 bus_slot_disconnect(slot
);
205 if (slot
->destroy_callback
)
206 slot
->destroy_callback(slot
->userdata
);
208 free(slot
->description
);
212 _public_ sd_bus
* sd_bus_slot_get_bus(sd_bus_slot
*slot
) {
213 assert_return(slot
, NULL
);
218 _public_
void *sd_bus_slot_get_userdata(sd_bus_slot
*slot
) {
219 assert_return(slot
, NULL
);
221 return slot
->userdata
;
224 _public_
void *sd_bus_slot_set_userdata(sd_bus_slot
*slot
, void *userdata
) {
227 assert_return(slot
, NULL
);
229 ret
= slot
->userdata
;
230 slot
->userdata
= userdata
;
235 _public_
int sd_bus_slot_set_destroy_callback(sd_bus_slot
*slot
, sd_bus_destroy_t callback
) {
236 assert_return(slot
, -EINVAL
);
238 slot
->destroy_callback
= callback
;
242 _public_
int sd_bus_slot_get_destroy_callback(sd_bus_slot
*slot
, sd_bus_destroy_t
*callback
) {
243 assert_return(slot
, -EINVAL
);
246 *callback
= slot
->destroy_callback
;
248 return !!slot
->destroy_callback
;
251 _public_ sd_bus_message
*sd_bus_slot_get_current_message(sd_bus_slot
*slot
) {
252 assert_return(slot
, NULL
);
253 assert_return(slot
->type
>= 0, NULL
);
255 if (slot
->bus
->current_slot
!= slot
)
258 return slot
->bus
->current_message
;
261 _public_ sd_bus_message_handler_t
sd_bus_slot_get_current_handler(sd_bus_slot
*slot
) {
262 assert_return(slot
, NULL
);
263 assert_return(slot
->type
>= 0, NULL
);
265 if (slot
->bus
->current_slot
!= slot
)
268 return slot
->bus
->current_handler
;
271 _public_
void* sd_bus_slot_get_current_userdata(sd_bus_slot
*slot
) {
272 assert_return(slot
, NULL
);
273 assert_return(slot
->type
>= 0, NULL
);
275 if (slot
->bus
->current_slot
!= slot
)
278 return slot
->bus
->current_userdata
;
281 _public_
int sd_bus_slot_get_floating(sd_bus_slot
*slot
) {
282 assert_return(slot
, -EINVAL
);
284 return slot
->floating
;
287 _public_
int sd_bus_slot_set_floating(sd_bus_slot
*slot
, int b
) {
288 assert_return(slot
, -EINVAL
);
290 if (slot
->floating
== !!b
)
293 if (!slot
->bus
) /* already disconnected slots can't be reconnected */
298 /* When a slot is "floating" then the bus references the slot. Otherwise the slot references the bus. Hence,
299 * when we move from one to the other, let's increase one reference and decrease the other. */
302 sd_bus_slot_ref(slot
);
303 sd_bus_unref(slot
->bus
);
305 sd_bus_ref(slot
->bus
);
306 sd_bus_slot_unref(slot
);
312 _public_
int sd_bus_slot_set_description(sd_bus_slot
*slot
, const char *description
) {
313 assert_return(slot
, -EINVAL
);
315 return free_and_strdup(&slot
->description
, description
);
318 _public_
int sd_bus_slot_get_description(sd_bus_slot
*slot
, const char **description
) {
319 assert_return(slot
, -EINVAL
);
320 assert_return(description
, -EINVAL
);
322 if (slot
->description
)
323 *description
= slot
->description
;
324 else if (slot
->type
== BUS_MATCH_CALLBACK
)
325 *description
= slot
->match_callback
.match_string
;