chiark / gitweb /
resolved: add bus API for configuring per-link DNS settings
[elogind.git] / src / libelogind / 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 #if 0 /// UNNEEDED by elogind
223 _public_ sd_bus* sd_bus_slot_get_bus(sd_bus_slot *slot) {
224         assert_return(slot, NULL);
225
226         return slot->bus;
227 }
228
229 _public_ void *sd_bus_slot_get_userdata(sd_bus_slot *slot) {
230         assert_return(slot, NULL);
231
232         return slot->userdata;
233 }
234
235 _public_ void *sd_bus_slot_set_userdata(sd_bus_slot *slot, void *userdata) {
236         void *ret;
237
238         assert_return(slot, NULL);
239
240         ret = slot->userdata;
241         slot->userdata = userdata;
242
243         return ret;
244 }
245
246 _public_ sd_bus_message *sd_bus_slot_get_current_message(sd_bus_slot *slot) {
247         assert_return(slot, NULL);
248         assert_return(slot->type >= 0, NULL);
249
250         if (slot->bus->current_slot != slot)
251                 return NULL;
252
253         return slot->bus->current_message;
254 }
255
256 _public_ sd_bus_message_handler_t sd_bus_slot_get_current_handler(sd_bus_slot *slot) {
257         assert_return(slot, NULL);
258         assert_return(slot->type >= 0, NULL);
259
260         if (slot->bus->current_slot != slot)
261                 return NULL;
262
263         return slot->bus->current_handler;
264 }
265
266 _public_ void* sd_bus_slot_get_current_userdata(sd_bus_slot *slot) {
267         assert_return(slot, NULL);
268         assert_return(slot->type >= 0, NULL);
269
270         if (slot->bus->current_slot != slot)
271                 return NULL;
272
273         return slot->bus->current_userdata;
274 }
275
276 _public_ int sd_bus_slot_set_description(sd_bus_slot *slot, const char *description) {
277         assert_return(slot, -EINVAL);
278
279         return free_and_strdup(&slot->description, description);
280 }
281
282 _public_ int sd_bus_slot_get_description(sd_bus_slot *slot, const char **description) {
283         assert_return(slot, -EINVAL);
284         assert_return(description, -EINVAL);
285         assert_return(slot->description, -ENXIO);
286
287         *description = slot->description;
288         return 0;
289 }
290 #endif // 0