]> git.proxmox.com Git - systemd.git/blob - src/libsystemd/sd-bus/bus-slot.c
Merge tag 'upstream/229'
[systemd.git] / src / libsystemd / sd-bus / bus-slot.c
1 /***
2 This file is part of systemd.
3
4 Copyright 2013 Lennart Poettering
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #include "sd-bus.h"
21
22 #include "alloc-util.h"
23 #include "bus-control.h"
24 #include "bus-objects.h"
25 #include "bus-slot.h"
26 #include "string-util.h"
27
28 sd_bus_slot *bus_slot_allocate(
29 sd_bus *bus,
30 bool floating,
31 BusSlotType type,
32 size_t extra,
33 void *userdata) {
34
35 sd_bus_slot *slot;
36
37 assert(bus);
38
39 slot = malloc0(offsetof(sd_bus_slot, reply_callback) + extra);
40 if (!slot)
41 return NULL;
42
43 slot->n_ref = 1;
44 slot->type = type;
45 slot->bus = bus;
46 slot->floating = floating;
47 slot->userdata = userdata;
48
49 if (!floating)
50 sd_bus_ref(bus);
51
52 LIST_PREPEND(slots, bus->slots, slot);
53
54 return slot;
55 }
56
57 _public_ sd_bus_slot* sd_bus_slot_ref(sd_bus_slot *slot) {
58
59 if (!slot)
60 return 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 }