]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-bus/bus-slot.c
Merge pull request #17549 from yuwata/tiny-fixes
[thirdparty/systemd.git] / src / libsystemd / sd-bus / bus-slot.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
19befb2d
LP
2
3#include "sd-bus.h"
07630cea 4
b5efdb8a 5#include "alloc-util.h"
19befb2d
LP
6#include "bus-control.h"
7#include "bus-objects.h"
8#include "bus-slot.h"
cf0fbc49 9#include "string-util.h"
19befb2d
LP
10
11sd_bus_slot *bus_slot_allocate(
12 sd_bus *bus,
13 bool floating,
14 BusSlotType type,
15 size_t extra,
16 void *userdata) {
17
18 sd_bus_slot *slot;
19
20 assert(bus);
21
22 slot = malloc0(offsetof(sd_bus_slot, reply_callback) + extra);
23 if (!slot)
24 return NULL;
25
26 slot->n_ref = 1;
27 slot->type = type;
28 slot->bus = bus;
29 slot->floating = floating;
30 slot->userdata = userdata;
31
32 if (!floating)
33 sd_bus_ref(bus);
34
35 LIST_PREPEND(slots, bus->slots, slot);
36
37 return slot;
38}
39
2e7e8e34 40void bus_slot_disconnect(sd_bus_slot *slot, bool unref) {
19befb2d
LP
41 sd_bus *bus;
42
43 assert(slot);
44
a71fe8b8 45 if (!slot->bus)
19befb2d
LP
46 return;
47
a71fe8b8
LP
48 switch (slot->type) {
49
19befb2d
LP
50 case BUS_REPLY_CALLBACK:
51
52 if (slot->reply_callback.cookie != 0)
c9fe4af7 53 ordered_hashmap_remove(slot->bus->reply_callbacks, &slot->reply_callback.cookie);
19befb2d 54
ac8029fc 55 if (slot->reply_callback.timeout_usec != 0)
19befb2d
LP
56 prioq_remove(slot->bus->reply_callbacks_prioq, &slot->reply_callback, &slot->reply_callback.prioq_idx);
57
58 break;
59
60 case BUS_FILTER_CALLBACK:
61 slot->bus->filter_callbacks_modified = true;
62 LIST_REMOVE(callbacks, slot->bus->filter_callbacks, &slot->filter_callback);
63 break;
64
65 case BUS_MATCH_CALLBACK:
66
cc65fe5e 67 if (slot->match_added)
acd34015 68 (void) bus_remove_match_internal(slot->bus, slot->match_callback.match_string);
19befb2d 69
7593c7a4 70 if (slot->match_callback.install_slot) {
2e7e8e34 71 bus_slot_disconnect(slot->match_callback.install_slot, true);
7593c7a4
LP
72 slot->match_callback.install_slot = sd_bus_slot_unref(slot->match_callback.install_slot);
73 }
74
19befb2d
LP
75 slot->bus->match_callbacks_modified = true;
76 bus_match_remove(&slot->bus->match_callbacks, &slot->match_callback);
77
45754e01 78 slot->match_callback.match_string = mfree(slot->match_callback.match_string);
19befb2d
LP
79
80 break;
81
82 case BUS_NODE_CALLBACK:
83
84 if (slot->node_callback.node) {
85 LIST_REMOVE(callbacks, slot->node_callback.node->callbacks, &slot->node_callback);
86 slot->bus->nodes_modified = true;
87
88 bus_node_gc(slot->bus, slot->node_callback.node);
89 }
90
91 break;
92
93 case BUS_NODE_ENUMERATOR:
94
95 if (slot->node_enumerator.node) {
96 LIST_REMOVE(enumerators, slot->node_enumerator.node->enumerators, &slot->node_enumerator);
97 slot->bus->nodes_modified = true;
98
99 bus_node_gc(slot->bus, slot->node_enumerator.node);
100 }
101
102 break;
103
104 case BUS_NODE_OBJECT_MANAGER:
105
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;
109
110 bus_node_gc(slot->bus, slot->node_object_manager.node);
111 }
112
113 break;
114
115 case BUS_NODE_VTABLE:
116
117 if (slot->node_vtable.node && slot->node_vtable.interface && slot->node_vtable.vtable) {
118 const sd_bus_vtable *v;
119
856ad2a8 120 for (v = slot->node_vtable.vtable; v->type != _SD_BUS_VTABLE_END; v = bus_vtable_next(slot->node_vtable.vtable, v)) {
19befb2d
LP
121 struct vtable_member *x = NULL;
122
123 switch (v->type) {
124
125 case _SD_BUS_VTABLE_METHOD: {
126 struct vtable_member key;
127
128 key.path = slot->node_vtable.node->path;
129 key.interface = slot->node_vtable.interface;
130 key.member = v->x.method.member;
131
132 x = hashmap_remove(slot->bus->vtable_methods, &key);
133 break;
134 }
135
136 case _SD_BUS_VTABLE_PROPERTY:
137 case _SD_BUS_VTABLE_WRITABLE_PROPERTY: {
138 struct vtable_member key;
139
140 key.path = slot->node_vtable.node->path;
141 key.interface = slot->node_vtable.interface;
142 key.member = v->x.method.member;
143
19befb2d
LP
144 x = hashmap_remove(slot->bus->vtable_properties, &key);
145 break;
146 }}
147
148 free(x);
149 }
150 }
151
45754e01 152 slot->node_vtable.interface = mfree(slot->node_vtable.interface);
19befb2d
LP
153
154 if (slot->node_vtable.node) {
155 LIST_REMOVE(vtables, slot->node_vtable.node->vtables, &slot->node_vtable);
156 slot->bus->nodes_modified = true;
157
158 bus_node_gc(slot->bus, slot->node_vtable.node);
159 }
160
161 break;
a71fe8b8
LP
162
163 default:
164 assert_not_reached("Wut? Unknown slot type?");
19befb2d 165 }
a71fe8b8 166
19befb2d
LP
167 bus = slot->bus;
168
a71fe8b8 169 slot->type = _BUS_SLOT_INVALID;
19befb2d
LP
170 slot->bus = NULL;
171 LIST_REMOVE(slots, bus->slots, slot);
172
173 if (!slot->floating)
174 sd_bus_unref(bus);
2e7e8e34
YW
175 else if (unref)
176 sd_bus_slot_unref(slot);
19befb2d
LP
177}
178
8301aa0b
YW
179static sd_bus_slot* bus_slot_free(sd_bus_slot *slot) {
180 assert(slot);
19befb2d 181
2e7e8e34 182 bus_slot_disconnect(slot, false);
fa17b4e8
ZJS
183
184 if (slot->destroy_callback)
185 slot->destroy_callback(slot->userdata);
186
9cbfc66c 187 free(slot->description);
6b430fdb 188 return mfree(slot);
19befb2d
LP
189}
190
8301aa0b
YW
191DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_bus_slot, sd_bus_slot, bus_slot_free);
192
19befb2d
LP
193_public_ sd_bus* sd_bus_slot_get_bus(sd_bus_slot *slot) {
194 assert_return(slot, NULL);
195
196 return slot->bus;
197}
198
199_public_ void *sd_bus_slot_get_userdata(sd_bus_slot *slot) {
200 assert_return(slot, NULL);
201
202 return slot->userdata;
203}
204
205_public_ void *sd_bus_slot_set_userdata(sd_bus_slot *slot, void *userdata) {
206 void *ret;
207
208 assert_return(slot, NULL);
209
210 ret = slot->userdata;
211 slot->userdata = userdata;
212
213 return ret;
214}
215
fa17b4e8
ZJS
216_public_ int sd_bus_slot_set_destroy_callback(sd_bus_slot *slot, sd_bus_destroy_t callback) {
217 assert_return(slot, -EINVAL);
218
219 slot->destroy_callback = callback;
220 return 0;
221}
222
223_public_ int sd_bus_slot_get_destroy_callback(sd_bus_slot *slot, sd_bus_destroy_t *callback) {
224 assert_return(slot, -EINVAL);
225
226 if (callback)
227 *callback = slot->destroy_callback;
228
229 return !!slot->destroy_callback;
230}
231
19befb2d
LP
232_public_ sd_bus_message *sd_bus_slot_get_current_message(sd_bus_slot *slot) {
233 assert_return(slot, NULL);
a71fe8b8 234 assert_return(slot->type >= 0, NULL);
19befb2d
LP
235
236 if (slot->bus->current_slot != slot)
237 return NULL;
238
239 return slot->bus->current_message;
240}
caa82984
LP
241
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);
245
246 if (slot->bus->current_slot != slot)
247 return NULL;
248
249 return slot->bus->current_handler;
250}
251
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);
255
256 if (slot->bus->current_slot != slot)
257 return NULL;
258
259 return slot->bus->current_userdata;
260}
9cbfc66c 261
303acb7f
LP
262_public_ int sd_bus_slot_get_floating(sd_bus_slot *slot) {
263 assert_return(slot, -EINVAL);
264
265 return slot->floating;
266}
267
268_public_ int sd_bus_slot_set_floating(sd_bus_slot *slot, int b) {
269 assert_return(slot, -EINVAL);
270
271 if (slot->floating == !!b)
272 return 0;
273
274 if (!slot->bus) /* already disconnected slots can't be reconnected */
275 return -ESTALE;
276
277 slot->floating = b;
278
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. */
281
282 if (b) {
283 sd_bus_slot_ref(slot);
284 sd_bus_unref(slot->bus);
285 } else {
286 sd_bus_ref(slot->bus);
287 sd_bus_slot_unref(slot);
288 }
289
290 return 1;
291}
292
9cbfc66c
LP
293_public_ int sd_bus_slot_set_description(sd_bus_slot *slot, const char *description) {
294 assert_return(slot, -EINVAL);
295
296 return free_and_strdup(&slot->description, description);
297}
298
839b6dbb 299_public_ int sd_bus_slot_get_description(sd_bus_slot *slot, const char **description) {
9cbfc66c
LP
300 assert_return(slot, -EINVAL);
301 assert_return(description, -EINVAL);
9cbfc66c 302
7ae497b9
LP
303 if (slot->description)
304 *description = slot->description;
305 else if (slot->type == BUS_MATCH_CALLBACK)
306 *description = slot->match_callback.match_string;
307 else
308 return -ENXIO;
309
9cbfc66c
LP
310 return 0;
311}