]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-bus/bus-slot.c
sd-event: introduce concept of "floating" event sources
[thirdparty/systemd.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 }