]>
Commit | Line | Data |
---|---|---|
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 | |
11 | sd_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 | 40 | void 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 |
179 | static 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 |
191 | DEFINE_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 | } |