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