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