]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-bus/bus-slot.c
util-lib: split our string related calls from util.[ch] into its own file string...
[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 "bus-control.h"
25 #include "bus-objects.h"
26 #include "string-util.h"
27 #include "bus-slot.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 assert_return(slot, NULL);
60
61 assert(slot->n_ref > 0);
62
63 slot->n_ref++;
64 return slot;
65 }
66
67 void bus_slot_disconnect(sd_bus_slot *slot) {
68 sd_bus *bus;
69
70 assert(slot);
71
72 if (!slot->bus)
73 return;
74
75 switch (slot->type) {
76
77 case BUS_REPLY_CALLBACK:
78
79 if (slot->reply_callback.cookie != 0)
80 ordered_hashmap_remove(slot->bus->reply_callbacks, &slot->reply_callback.cookie);
81
82 if (slot->reply_callback.timeout != 0)
83 prioq_remove(slot->bus->reply_callbacks_prioq, &slot->reply_callback, &slot->reply_callback.prioq_idx);
84
85 break;
86
87 case BUS_FILTER_CALLBACK:
88 slot->bus->filter_callbacks_modified = true;
89 LIST_REMOVE(callbacks, slot->bus->filter_callbacks, &slot->filter_callback);
90 break;
91
92 case BUS_MATCH_CALLBACK:
93
94 if (slot->match_added)
95 bus_remove_match_internal(slot->bus, slot->match_callback.match_string, slot->match_callback.cookie);
96
97 slot->bus->match_callbacks_modified = true;
98 bus_match_remove(&slot->bus->match_callbacks, &slot->match_callback);
99
100 free(slot->match_callback.match_string);
101
102 break;
103
104 case BUS_NODE_CALLBACK:
105
106 if (slot->node_callback.node) {
107 LIST_REMOVE(callbacks, slot->node_callback.node->callbacks, &slot->node_callback);
108 slot->bus->nodes_modified = true;
109
110 bus_node_gc(slot->bus, slot->node_callback.node);
111 }
112
113 break;
114
115 case BUS_NODE_ENUMERATOR:
116
117 if (slot->node_enumerator.node) {
118 LIST_REMOVE(enumerators, slot->node_enumerator.node->enumerators, &slot->node_enumerator);
119 slot->bus->nodes_modified = true;
120
121 bus_node_gc(slot->bus, slot->node_enumerator.node);
122 }
123
124 break;
125
126 case BUS_NODE_OBJECT_MANAGER:
127
128 if (slot->node_object_manager.node) {
129 LIST_REMOVE(object_managers, slot->node_object_manager.node->object_managers, &slot->node_object_manager);
130 slot->bus->nodes_modified = true;
131
132 bus_node_gc(slot->bus, slot->node_object_manager.node);
133 }
134
135 break;
136
137 case BUS_NODE_VTABLE:
138
139 if (slot->node_vtable.node && slot->node_vtable.interface && slot->node_vtable.vtable) {
140 const sd_bus_vtable *v;
141
142 for (v = slot->node_vtable.vtable; v->type != _SD_BUS_VTABLE_END; v++) {
143 struct vtable_member *x = NULL;
144
145 switch (v->type) {
146
147 case _SD_BUS_VTABLE_METHOD: {
148 struct vtable_member key;
149
150 key.path = slot->node_vtable.node->path;
151 key.interface = slot->node_vtable.interface;
152 key.member = v->x.method.member;
153
154 x = hashmap_remove(slot->bus->vtable_methods, &key);
155 break;
156 }
157
158 case _SD_BUS_VTABLE_PROPERTY:
159 case _SD_BUS_VTABLE_WRITABLE_PROPERTY: {
160 struct vtable_member key;
161
162 key.path = slot->node_vtable.node->path;
163 key.interface = slot->node_vtable.interface;
164 key.member = v->x.method.member;
165
166
167 x = hashmap_remove(slot->bus->vtable_properties, &key);
168 break;
169 }}
170
171 free(x);
172 }
173 }
174
175 free(slot->node_vtable.interface);
176
177 if (slot->node_vtable.node) {
178 LIST_REMOVE(vtables, slot->node_vtable.node->vtables, &slot->node_vtable);
179 slot->bus->nodes_modified = true;
180
181 bus_node_gc(slot->bus, slot->node_vtable.node);
182 }
183
184 break;
185
186 default:
187 assert_not_reached("Wut? Unknown slot type?");
188 }
189
190 bus = slot->bus;
191
192 slot->type = _BUS_SLOT_INVALID;
193 slot->bus = NULL;
194 LIST_REMOVE(slots, bus->slots, slot);
195
196 if (!slot->floating)
197 sd_bus_unref(bus);
198 }
199
200 _public_ sd_bus_slot* sd_bus_slot_unref(sd_bus_slot *slot) {
201
202 if (!slot)
203 return NULL;
204
205 assert(slot->n_ref > 0);
206
207 if (slot->n_ref > 1) {
208 slot->n_ref --;
209 return NULL;
210 }
211
212 bus_slot_disconnect(slot);
213 free(slot->description);
214 free(slot);
215
216 return NULL;
217 }
218
219 _public_ sd_bus* sd_bus_slot_get_bus(sd_bus_slot *slot) {
220 assert_return(slot, NULL);
221
222 return slot->bus;
223 }
224
225 _public_ void *sd_bus_slot_get_userdata(sd_bus_slot *slot) {
226 assert_return(slot, NULL);
227
228 return slot->userdata;
229 }
230
231 _public_ void *sd_bus_slot_set_userdata(sd_bus_slot *slot, void *userdata) {
232 void *ret;
233
234 assert_return(slot, NULL);
235
236 ret = slot->userdata;
237 slot->userdata = userdata;
238
239 return ret;
240 }
241
242 _public_ sd_bus_message *sd_bus_slot_get_current_message(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_message;
250 }
251
252 _public_ sd_bus_message_handler_t sd_bus_slot_get_current_handler(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_handler;
260 }
261
262 _public_ void* sd_bus_slot_get_current_userdata(sd_bus_slot *slot) {
263 assert_return(slot, NULL);
264 assert_return(slot->type >= 0, NULL);
265
266 if (slot->bus->current_slot != slot)
267 return NULL;
268
269 return slot->bus->current_userdata;
270 }
271
272 _public_ int sd_bus_slot_set_description(sd_bus_slot *slot, const char *description) {
273 assert_return(slot, -EINVAL);
274
275 return free_and_strdup(&slot->description, description);
276 }
277
278 _public_ int sd_bus_slot_get_description(sd_bus_slot *slot, const char **description) {
279 assert_return(slot, -EINVAL);
280 assert_return(description, -EINVAL);
281 assert_return(slot->description, -ENXIO);
282
283 *description = slot->description;
284 return 0;
285 }