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