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