1 /* SPDX-License-Identifier: LGPL-2.1+ */
7 #include "alloc-util.h"
8 #include "bus-control.h"
9 #include "bus-objects.h"
11 #include "string-util.h"
13 sd_bus_slot
*bus_slot_allocate(
24 slot
= malloc0(offsetof(sd_bus_slot
, reply_callback
) + extra
);
31 slot
->floating
= floating
;
32 slot
->userdata
= userdata
;
37 LIST_PREPEND(slots
, bus
->slots
, slot
);
42 _public_ sd_bus_slot
* sd_bus_slot_ref(sd_bus_slot
*slot
) {
47 assert(slot
->n_ref
> 0);
53 void bus_slot_disconnect(sd_bus_slot
*slot
) {
63 case BUS_REPLY_CALLBACK
:
65 if (slot
->reply_callback
.cookie
!= 0)
66 ordered_hashmap_remove(slot
->bus
->reply_callbacks
, &slot
->reply_callback
.cookie
);
68 if (slot
->reply_callback
.timeout_usec
!= 0)
69 prioq_remove(slot
->bus
->reply_callbacks_prioq
, &slot
->reply_callback
, &slot
->reply_callback
.prioq_idx
);
73 case BUS_FILTER_CALLBACK
:
74 slot
->bus
->filter_callbacks_modified
= true;
75 LIST_REMOVE(callbacks
, slot
->bus
->filter_callbacks
, &slot
->filter_callback
);
78 case BUS_MATCH_CALLBACK
:
80 if (slot
->match_added
)
81 (void) bus_remove_match_internal(slot
->bus
, slot
->match_callback
.match_string
);
83 if (slot
->match_callback
.install_slot
) {
84 bus_slot_disconnect(slot
->match_callback
.install_slot
);
85 slot
->match_callback
.install_slot
= sd_bus_slot_unref(slot
->match_callback
.install_slot
);
88 slot
->bus
->match_callbacks_modified
= true;
89 bus_match_remove(&slot
->bus
->match_callbacks
, &slot
->match_callback
);
91 slot
->match_callback
.match_string
= mfree(slot
->match_callback
.match_string
);
95 case BUS_NODE_CALLBACK
:
97 if (slot
->node_callback
.node
) {
98 LIST_REMOVE(callbacks
, slot
->node_callback
.node
->callbacks
, &slot
->node_callback
);
99 slot
->bus
->nodes_modified
= true;
101 bus_node_gc(slot
->bus
, slot
->node_callback
.node
);
106 case BUS_NODE_ENUMERATOR
:
108 if (slot
->node_enumerator
.node
) {
109 LIST_REMOVE(enumerators
, slot
->node_enumerator
.node
->enumerators
, &slot
->node_enumerator
);
110 slot
->bus
->nodes_modified
= true;
112 bus_node_gc(slot
->bus
, slot
->node_enumerator
.node
);
117 case BUS_NODE_OBJECT_MANAGER
:
119 if (slot
->node_object_manager
.node
) {
120 LIST_REMOVE(object_managers
, slot
->node_object_manager
.node
->object_managers
, &slot
->node_object_manager
);
121 slot
->bus
->nodes_modified
= true;
123 bus_node_gc(slot
->bus
, slot
->node_object_manager
.node
);
128 case BUS_NODE_VTABLE
:
130 if (slot
->node_vtable
.node
&& slot
->node_vtable
.interface
&& slot
->node_vtable
.vtable
) {
131 const sd_bus_vtable
*v
;
133 for (v
= slot
->node_vtable
.vtable
; v
->type
!= _SD_BUS_VTABLE_END
; v
++) {
134 struct vtable_member
*x
= NULL
;
138 case _SD_BUS_VTABLE_METHOD
: {
139 struct vtable_member key
;
141 key
.path
= slot
->node_vtable
.node
->path
;
142 key
.interface
= slot
->node_vtable
.interface
;
143 key
.member
= v
->x
.method
.member
;
145 x
= hashmap_remove(slot
->bus
->vtable_methods
, &key
);
149 case _SD_BUS_VTABLE_PROPERTY
:
150 case _SD_BUS_VTABLE_WRITABLE_PROPERTY
: {
151 struct vtable_member key
;
153 key
.path
= slot
->node_vtable
.node
->path
;
154 key
.interface
= slot
->node_vtable
.interface
;
155 key
.member
= v
->x
.method
.member
;
157 x
= hashmap_remove(slot
->bus
->vtable_properties
, &key
);
165 slot
->node_vtable
.interface
= mfree(slot
->node_vtable
.interface
);
167 if (slot
->node_vtable
.node
) {
168 LIST_REMOVE(vtables
, slot
->node_vtable
.node
->vtables
, &slot
->node_vtable
);
169 slot
->bus
->nodes_modified
= true;
171 bus_node_gc(slot
->bus
, slot
->node_vtable
.node
);
177 assert_not_reached("Wut? Unknown slot type?");
182 slot
->type
= _BUS_SLOT_INVALID
;
184 LIST_REMOVE(slots
, bus
->slots
, slot
);
190 _public_ sd_bus_slot
* sd_bus_slot_unref(sd_bus_slot
*slot
) {
195 assert(slot
->n_ref
> 0);
197 if (slot
->n_ref
> 1) {
202 bus_slot_disconnect(slot
);
204 if (slot
->destroy_callback
)
205 slot
->destroy_callback(slot
->userdata
);
207 free(slot
->description
);
211 _public_ sd_bus
* sd_bus_slot_get_bus(sd_bus_slot
*slot
) {
212 assert_return(slot
, NULL
);
217 _public_
void *sd_bus_slot_get_userdata(sd_bus_slot
*slot
) {
218 assert_return(slot
, NULL
);
220 return slot
->userdata
;
223 _public_
void *sd_bus_slot_set_userdata(sd_bus_slot
*slot
, void *userdata
) {
226 assert_return(slot
, NULL
);
228 ret
= slot
->userdata
;
229 slot
->userdata
= userdata
;
234 _public_
int sd_bus_slot_set_destroy_callback(sd_bus_slot
*slot
, sd_bus_destroy_t callback
) {
235 assert_return(slot
, -EINVAL
);
237 slot
->destroy_callback
= callback
;
241 _public_
int sd_bus_slot_get_destroy_callback(sd_bus_slot
*slot
, sd_bus_destroy_t
*callback
) {
242 assert_return(slot
, -EINVAL
);
245 *callback
= slot
->destroy_callback
;
247 return !!slot
->destroy_callback
;
250 _public_ sd_bus_message
*sd_bus_slot_get_current_message(sd_bus_slot
*slot
) {
251 assert_return(slot
, NULL
);
252 assert_return(slot
->type
>= 0, NULL
);
254 if (slot
->bus
->current_slot
!= slot
)
257 return slot
->bus
->current_message
;
260 _public_ sd_bus_message_handler_t
sd_bus_slot_get_current_handler(sd_bus_slot
*slot
) {
261 assert_return(slot
, NULL
);
262 assert_return(slot
->type
>= 0, NULL
);
264 if (slot
->bus
->current_slot
!= slot
)
267 return slot
->bus
->current_handler
;
270 _public_
void* sd_bus_slot_get_current_userdata(sd_bus_slot
*slot
) {
271 assert_return(slot
, NULL
);
272 assert_return(slot
->type
>= 0, NULL
);
274 if (slot
->bus
->current_slot
!= slot
)
277 return slot
->bus
->current_userdata
;
280 _public_
int sd_bus_slot_get_floating(sd_bus_slot
*slot
) {
281 assert_return(slot
, -EINVAL
);
283 return slot
->floating
;
286 _public_
int sd_bus_slot_set_floating(sd_bus_slot
*slot
, int b
) {
287 assert_return(slot
, -EINVAL
);
289 if (slot
->floating
== !!b
)
292 if (!slot
->bus
) /* already disconnected slots can't be reconnected */
297 /* When a slot is "floating" then the bus references the slot. Otherwise the slot references the bus. Hence,
298 * when we move from one to the other, let's increase one reference and decrease the other. */
301 sd_bus_slot_ref(slot
);
302 sd_bus_unref(slot
->bus
);
304 sd_bus_ref(slot
->bus
);
305 sd_bus_slot_unref(slot
);
311 _public_
int sd_bus_slot_set_description(sd_bus_slot
*slot
, const char *description
) {
312 assert_return(slot
, -EINVAL
);
314 return free_and_strdup(&slot
->description
, description
);
317 _public_
int sd_bus_slot_get_description(sd_bus_slot
*slot
, const char **description
) {
318 assert_return(slot
, -EINVAL
);
319 assert_return(description
, -EINVAL
);
321 if (slot
->description
)
322 *description
= slot
->description
;
323 else if (slot
->type
== BUS_MATCH_CALLBACK
)
324 *description
= slot
->match_callback
.match_string
;