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