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 _public_ sd_bus_slot
* sd_bus_slot_ref(sd_bus_slot
*slot
) {
45 assert(slot
->n_ref
> 0);
51 void bus_slot_disconnect(sd_bus_slot
*slot
, bool unref
) {
61 case BUS_REPLY_CALLBACK
:
63 if (slot
->reply_callback
.cookie
!= 0)
64 ordered_hashmap_remove(slot
->bus
->reply_callbacks
, &slot
->reply_callback
.cookie
);
66 if (slot
->reply_callback
.timeout_usec
!= 0)
67 prioq_remove(slot
->bus
->reply_callbacks_prioq
, &slot
->reply_callback
, &slot
->reply_callback
.prioq_idx
);
71 case BUS_FILTER_CALLBACK
:
72 slot
->bus
->filter_callbacks_modified
= true;
73 LIST_REMOVE(callbacks
, slot
->bus
->filter_callbacks
, &slot
->filter_callback
);
76 case BUS_MATCH_CALLBACK
:
78 if (slot
->match_added
)
79 (void) bus_remove_match_internal(slot
->bus
, slot
->match_callback
.match_string
);
81 if (slot
->match_callback
.install_slot
) {
82 bus_slot_disconnect(slot
->match_callback
.install_slot
, true);
83 slot
->match_callback
.install_slot
= sd_bus_slot_unref(slot
->match_callback
.install_slot
);
86 slot
->bus
->match_callbacks_modified
= true;
87 bus_match_remove(&slot
->bus
->match_callbacks
, &slot
->match_callback
);
89 slot
->match_callback
.match_string
= mfree(slot
->match_callback
.match_string
);
93 case BUS_NODE_CALLBACK
:
95 if (slot
->node_callback
.node
) {
96 LIST_REMOVE(callbacks
, slot
->node_callback
.node
->callbacks
, &slot
->node_callback
);
97 slot
->bus
->nodes_modified
= true;
99 bus_node_gc(slot
->bus
, slot
->node_callback
.node
);
104 case BUS_NODE_ENUMERATOR
:
106 if (slot
->node_enumerator
.node
) {
107 LIST_REMOVE(enumerators
, slot
->node_enumerator
.node
->enumerators
, &slot
->node_enumerator
);
108 slot
->bus
->nodes_modified
= true;
110 bus_node_gc(slot
->bus
, slot
->node_enumerator
.node
);
115 case BUS_NODE_OBJECT_MANAGER
:
117 if (slot
->node_object_manager
.node
) {
118 LIST_REMOVE(object_managers
, slot
->node_object_manager
.node
->object_managers
, &slot
->node_object_manager
);
119 slot
->bus
->nodes_modified
= true;
121 bus_node_gc(slot
->bus
, slot
->node_object_manager
.node
);
126 case BUS_NODE_VTABLE
:
128 if (slot
->node_vtable
.node
&& slot
->node_vtable
.interface
&& slot
->node_vtable
.vtable
) {
129 const sd_bus_vtable
*v
;
131 for (v
= slot
->node_vtable
.vtable
; v
->type
!= _SD_BUS_VTABLE_END
; v
++) {
132 struct vtable_member
*x
= NULL
;
136 case _SD_BUS_VTABLE_METHOD
: {
137 struct vtable_member key
;
139 key
.path
= slot
->node_vtable
.node
->path
;
140 key
.interface
= slot
->node_vtable
.interface
;
141 key
.member
= v
->x
.method
.member
;
143 x
= hashmap_remove(slot
->bus
->vtable_methods
, &key
);
147 case _SD_BUS_VTABLE_PROPERTY
:
148 case _SD_BUS_VTABLE_WRITABLE_PROPERTY
: {
149 struct vtable_member key
;
151 key
.path
= slot
->node_vtable
.node
->path
;
152 key
.interface
= slot
->node_vtable
.interface
;
153 key
.member
= v
->x
.method
.member
;
155 x
= hashmap_remove(slot
->bus
->vtable_properties
, &key
);
163 slot
->node_vtable
.interface
= mfree(slot
->node_vtable
.interface
);
165 if (slot
->node_vtable
.node
) {
166 LIST_REMOVE(vtables
, slot
->node_vtable
.node
->vtables
, &slot
->node_vtable
);
167 slot
->bus
->nodes_modified
= true;
169 bus_node_gc(slot
->bus
, slot
->node_vtable
.node
);
175 assert_not_reached("Wut? Unknown slot type?");
180 slot
->type
= _BUS_SLOT_INVALID
;
182 LIST_REMOVE(slots
, bus
->slots
, slot
);
187 sd_bus_slot_unref(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
, false);
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
;