]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-bus/bus-slot.c
9a563717152a8f99118ae3a1ea7640b161fe1c80
[thirdparty/systemd.git] / src / libsystemd / sd-bus / bus-slot.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2013 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include "sd-bus.h"
22
23 #include "alloc-util.h"
24 #include "bus-control.h"
25 #include "bus-objects.h"
26 #include "bus-slot.h"
27 #include "string-util.h"
28
29 sd_bus_slot *bus_slot_allocate(
30 sd_bus *bus,
31 bool floating,
32 BusSlotType type,
33 size_t extra,
34 void *userdata) {
35
36 sd_bus_slot *slot;
37
38 assert(bus);
39
40 slot = malloc0(offsetof(sd_bus_slot, reply_callback) + extra);
41 if (!slot)
42 return NULL;
43
44 slot->n_ref = 1;
45 slot->type = type;
46 slot->bus = bus;
47 slot->floating = floating;
48 slot->userdata = userdata;
49
50 if (!floating)
51 sd_bus_ref(bus);
52
53 LIST_PREPEND(slots, bus->slots, slot);
54
55 return slot;
56 }
57
58 _public_ sd_bus_slot* sd_bus_slot_ref(sd_bus_slot *slot) {
59
60 if (!slot)
61 return NULL;
62
63 assert(slot->n_ref > 0);
64
65 slot->n_ref++;
66 return slot;
67 }
68
69 void bus_slot_disconnect(sd_bus_slot *slot) {
70 sd_bus *bus;
71
72 assert(slot);
73
74 if (!slot->bus)
75 return;
76
77 switch (slot->type) {
78
79 case BUS_REPLY_CALLBACK:
80
81 if (slot->reply_callback.cookie != 0)
82 ordered_hashmap_remove(slot->bus->reply_callbacks, &slot->reply_callback.cookie);
83
84 if (slot->reply_callback.timeout_usec != 0)
85 prioq_remove(slot->bus->reply_callbacks_prioq, &slot->reply_callback, &slot->reply_callback.prioq_idx);
86
87 break;
88
89 case BUS_FILTER_CALLBACK:
90 slot->bus->filter_callbacks_modified = true;
91 LIST_REMOVE(callbacks, slot->bus->filter_callbacks, &slot->filter_callback);
92 break;
93
94 case BUS_MATCH_CALLBACK:
95
96 if (slot->match_added)
97 (void) bus_remove_match_internal(slot->bus, slot->match_callback.match_string);
98
99 if (slot->match_callback.install_slot) {
100 bus_slot_disconnect(slot->match_callback.install_slot);
101 slot->match_callback.install_slot = sd_bus_slot_unref(slot->match_callback.install_slot);
102 }
103
104 slot->bus->match_callbacks_modified = true;
105 bus_match_remove(&slot->bus->match_callbacks, &slot->match_callback);
106
107 slot->match_callback.match_string = mfree(slot->match_callback.match_string);
108
109 break;
110
111 case BUS_NODE_CALLBACK:
112
113 if (slot->node_callback.node) {
114 LIST_REMOVE(callbacks, slot->node_callback.node->callbacks, &slot->node_callback);
115 slot->bus->nodes_modified = true;
116
117 bus_node_gc(slot->bus, slot->node_callback.node);
118 }
119
120 break;
121
122 case BUS_NODE_ENUMERATOR:
123
124 if (slot->node_enumerator.node) {
125 LIST_REMOVE(enumerators, slot->node_enumerator.node->enumerators, &slot->node_enumerator);
126 slot->bus->nodes_modified = true;
127
128 bus_node_gc(slot->bus, slot->node_enumerator.node);
129 }
130
131 break;
132
133 case BUS_NODE_OBJECT_MANAGER:
134
135 if (slot->node_object_manager.node) {
136 LIST_REMOVE(object_managers, slot->node_object_manager.node->object_managers, &slot->node_object_manager);
137 slot->bus->nodes_modified = true;
138
139 bus_node_gc(slot->bus, slot->node_object_manager.node);
140 }
141
142 break;
143
144 case BUS_NODE_VTABLE:
145
146 if (slot->node_vtable.node && slot->node_vtable.interface && slot->node_vtable.vtable) {
147 const sd_bus_vtable *v;
148
149 for (v = slot->node_vtable.vtable; v->type != _SD_BUS_VTABLE_END; v++) {
150 struct vtable_member *x = NULL;
151
152 switch (v->type) {
153
154 case _SD_BUS_VTABLE_METHOD: {
155 struct vtable_member key;
156
157 key.path = slot->node_vtable.node->path;
158 key.interface = slot->node_vtable.interface;
159 key.member = v->x.method.member;
160
161 x = hashmap_remove(slot->bus->vtable_methods, &key);
162 break;
163 }
164
165 case _SD_BUS_VTABLE_PROPERTY:
166 case _SD_BUS_VTABLE_WRITABLE_PROPERTY: {
167 struct vtable_member key;
168
169 key.path = slot->node_vtable.node->path;
170 key.interface = slot->node_vtable.interface;
171 key.member = v->x.method.member;
172
173
174 x = hashmap_remove(slot->bus->vtable_properties, &key);
175 break;
176 }}
177
178 free(x);
179 }
180 }
181
182 slot->node_vtable.interface = mfree(slot->node_vtable.interface);
183
184 if (slot->node_vtable.node) {
185 LIST_REMOVE(vtables, slot->node_vtable.node->vtables, &slot->node_vtable);
186 slot->bus->nodes_modified = true;
187
188 bus_node_gc(slot->bus, slot->node_vtable.node);
189 }
190
191 break;
192
193 default:
194 assert_not_reached("Wut? Unknown slot type?");
195 }
196
197 bus = slot->bus;
198
199 slot->type = _BUS_SLOT_INVALID;
200 slot->bus = NULL;
201 LIST_REMOVE(slots, bus->slots, slot);
202
203 if (!slot->floating)
204 sd_bus_unref(bus);
205 }
206
207 _public_ sd_bus_slot* sd_bus_slot_unref(sd_bus_slot *slot) {
208
209 if (!slot)
210 return NULL;
211
212 assert(slot->n_ref > 0);
213
214 if (slot->n_ref > 1) {
215 slot->n_ref--;
216 return NULL;
217 }
218
219 bus_slot_disconnect(slot);
220 free(slot->description);
221 return mfree(slot);
222 }
223
224 _public_ sd_bus* sd_bus_slot_get_bus(sd_bus_slot *slot) {
225 assert_return(slot, NULL);
226
227 return slot->bus;
228 }
229
230 _public_ void *sd_bus_slot_get_userdata(sd_bus_slot *slot) {
231 assert_return(slot, NULL);
232
233 return slot->userdata;
234 }
235
236 _public_ void *sd_bus_slot_set_userdata(sd_bus_slot *slot, void *userdata) {
237 void *ret;
238
239 assert_return(slot, NULL);
240
241 ret = slot->userdata;
242 slot->userdata = userdata;
243
244 return ret;
245 }
246
247 _public_ sd_bus_message *sd_bus_slot_get_current_message(sd_bus_slot *slot) {
248 assert_return(slot, NULL);
249 assert_return(slot->type >= 0, NULL);
250
251 if (slot->bus->current_slot != slot)
252 return NULL;
253
254 return slot->bus->current_message;
255 }
256
257 _public_ sd_bus_message_handler_t sd_bus_slot_get_current_handler(sd_bus_slot *slot) {
258 assert_return(slot, NULL);
259 assert_return(slot->type >= 0, NULL);
260
261 if (slot->bus->current_slot != slot)
262 return NULL;
263
264 return slot->bus->current_handler;
265 }
266
267 _public_ void* sd_bus_slot_get_current_userdata(sd_bus_slot *slot) {
268 assert_return(slot, NULL);
269 assert_return(slot->type >= 0, NULL);
270
271 if (slot->bus->current_slot != slot)
272 return NULL;
273
274 return slot->bus->current_userdata;
275 }
276
277 _public_ int sd_bus_slot_set_description(sd_bus_slot *slot, const char *description) {
278 assert_return(slot, -EINVAL);
279
280 return free_and_strdup(&slot->description, description);
281 }
282
283 _public_ int sd_bus_slot_get_description(sd_bus_slot *slot, const char **description) {
284 assert_return(slot, -EINVAL);
285 assert_return(description, -EINVAL);
286 assert_return(slot->description, -ENXIO);
287
288 *description = slot->description;
289 return 0;
290 }