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