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