blob: 8bb42e9c5c7dbaa21c2195c8b00e36bf385871a3 [file] [log] [blame]
Brad Bishop62ece2b2016-07-25 09:00:51 -04001/**
2 * Copyright © 2016 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Brad Bishop36eb1e52016-11-01 15:18:36 -040016#include "config.h"
Brad Bishop2afe7182016-08-13 14:08:17 -040017#include <stdlib.h>
Brad Bishop62ece2b2016-07-25 09:00:51 -040018#include <string.h>
Brad Bishop2afe7182016-08-13 14:08:17 -040019#include <stdio.h>
20#include <errno.h>
Brad Bishop3d468792016-09-20 15:39:38 -040021#include <unistd.h>
22#include <sys/timerfd.h>
Brad Bishop62ece2b2016-07-25 09:00:51 -040023#include <systemd/sd-bus.h>
Brad Bishop3d468792016-09-20 15:39:38 -040024#include <systemd/sd-event.h>
Brad Bishop62ece2b2016-07-25 09:00:51 -040025#include "mapper.h"
26
Brad Bishop829181d2017-02-24 09:49:14 -050027static const char *async_wait_introspection_match =
Ed Tanous167e2372018-05-07 11:59:10 -070028 "type='signal',"
29 "sender='xyz.openbmc_project.ObjectMapper',"
30 "interface='xyz.openbmc_project.ObjectMapper.Private',"
31 "member='IntrospectionComplete'";
Brad Bishop2afe7182016-08-13 14:08:17 -040032
33static const char *async_wait_interfaces_added_match =
Ed Tanous167e2372018-05-07 11:59:10 -070034 "type='signal',"
35 "interface='org.freedesktop.DBus.ObjectManager',"
36 "member='InterfacesAdded'";
Brad Bishop2afe7182016-08-13 14:08:17 -040037
Adriana Kobylak78edbb62017-05-04 15:45:19 -050038static const char *interfaces_removed_match =
Ed Tanous167e2372018-05-07 11:59:10 -070039 "type='signal',"
40 "interface='org.freedesktop.DBus.ObjectManager',"
41 "member='InterfacesRemoved'";
Adriana Kobylak78edbb62017-05-04 15:45:19 -050042
Brad Bishop3d468792016-09-20 15:39:38 -040043static const int mapper_busy_retries = 5;
44static const uint64_t mapper_busy_delay_interval_usec = 1000000;
45
Brad Bishop2afe7182016-08-13 14:08:17 -040046struct mapper_async_wait
47{
Ed Tanous167e2372018-05-07 11:59:10 -070048 char **objs;
49 void (*callback)(int, void *);
50 void *userdata;
51 sd_event *loop;
52 sd_bus *conn;
53 sd_bus_slot *introspection_slot;
54 sd_bus_slot *intf_slot;
55 int *status;
56 int count;
57 int finished;
58 int r;
Brad Bishop2afe7182016-08-13 14:08:17 -040059};
60
61struct async_wait_callback_data
62{
Ed Tanous167e2372018-05-07 11:59:10 -070063 mapper_async_wait *wait;
64 const char *path;
65 sd_event_source *event_source;
66 int retry;
Brad Bishop2afe7182016-08-13 14:08:17 -040067};
68
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -050069struct mapper_async_subtree
70{
Ed Tanous167e2372018-05-07 11:59:10 -070071 char *namespace;
72 char *interface;
73 void (*callback)(int, void *);
74 void *userdata;
75 sd_event *loop;
76 sd_bus *conn;
77 sd_bus_slot *slot;
78 sd_event_source *event_source;
79 int finished;
80 int op;
81 int retry;
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -050082};
83
Brad Bishop829181d2017-02-24 09:49:14 -050084static int async_wait_match_introspection_complete(sd_bus_message *, void *,
Ed Tanous167e2372018-05-07 11:59:10 -070085 sd_bus_error *);
Brad Bishop2afe7182016-08-13 14:08:17 -040086static int async_wait_check_done(mapper_async_wait *);
87static void async_wait_done(int r, mapper_async_wait *);
88static int async_wait_get_objects(mapper_async_wait *);
Ed Tanous167e2372018-05-07 11:59:10 -070089static int async_wait_getobject_callback(sd_bus_message *, void *,
90 sd_bus_error *);
Brad Bishop2afe7182016-08-13 14:08:17 -040091
Adriana Kobylak78edbb62017-05-04 15:45:19 -050092static int async_subtree_match_callback(sd_bus_message *, void *,
Ed Tanous167e2372018-05-07 11:59:10 -070093 sd_bus_error *);
Adriana Kobylakb2f26812017-05-08 13:58:02 -050094static void async_subtree_done(int r, mapper_async_subtree *);
Adriana Kobylak025d7952017-05-08 13:30:45 -050095static int async_subtree_getpaths(mapper_async_subtree *);
Ed Tanous167e2372018-05-07 11:59:10 -070096static int async_subtree_getpaths_callback(sd_bus_message *, void *,
97 sd_bus_error *);
Adriana Kobylak78edbb62017-05-04 15:45:19 -050098
Brad Bishop2afe7182016-08-13 14:08:17 -040099static int sarraylen(char *array[])
100{
Ed Tanous167e2372018-05-07 11:59:10 -0700101 int count = 0;
102 char **p = array;
Brad Bishop2afe7182016-08-13 14:08:17 -0400103
Ed Tanous167e2372018-05-07 11:59:10 -0700104 while (*p != NULL)
105 {
106 ++count;
107 ++p;
108 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400109
Ed Tanous167e2372018-05-07 11:59:10 -0700110 return count;
Brad Bishop2afe7182016-08-13 14:08:17 -0400111}
112
113static void sarrayfree(char *array[])
114{
Ed Tanous167e2372018-05-07 11:59:10 -0700115 char **p = array;
116 while (*p != NULL)
117 {
118 free(*p);
119 ++p;
120 }
121 free(array);
Brad Bishop2afe7182016-08-13 14:08:17 -0400122}
123
124static char **sarraydup(char *array[])
125{
Ed Tanous167e2372018-05-07 11:59:10 -0700126 int count = sarraylen(array);
127 int i;
128 char **ret = NULL;
Brad Bishop2afe7182016-08-13 14:08:17 -0400129
Ed Tanous167e2372018-05-07 11:59:10 -0700130 ret = malloc(sizeof(*ret) * count);
131 if (!ret)
132 return NULL;
Brad Bishop2afe7182016-08-13 14:08:17 -0400133
Ed Tanous167e2372018-05-07 11:59:10 -0700134 for (i = 0; i < count; ++i)
135 {
136 ret[i] = strdup(array[i]);
137 if (!ret[i])
138 goto error;
139 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400140
Ed Tanous167e2372018-05-07 11:59:10 -0700141 return ret;
Brad Bishop2afe7182016-08-13 14:08:17 -0400142
143error:
Ed Tanous167e2372018-05-07 11:59:10 -0700144 sarrayfree(ret);
145 return NULL;
Brad Bishop2afe7182016-08-13 14:08:17 -0400146}
147
Ed Tanous167e2372018-05-07 11:59:10 -0700148static int async_wait_timeout_callback(sd_event_source *s, uint64_t usec,
149 void *userdata)
Brad Bishop3d468792016-09-20 15:39:38 -0400150{
Ed Tanous167e2372018-05-07 11:59:10 -0700151 int r;
152 struct async_wait_callback_data *data = userdata;
153 mapper_async_wait *wait = data->wait;
Brad Bishop3d468792016-09-20 15:39:38 -0400154
Ed Tanous167e2372018-05-07 11:59:10 -0700155 sd_event_source_unref(data->event_source);
156 r = sd_bus_call_method_async(wait->conn, NULL, MAPPER_BUSNAME, MAPPER_PATH,
157 MAPPER_INTERFACE, "GetObject",
158 async_wait_getobject_callback, data, "sas",
159 data->path, 0, NULL);
160 if (r < 0)
161 {
162 async_wait_done(r, wait);
163 free(data);
164 }
Brad Bishop3d468792016-09-20 15:39:38 -0400165
Ed Tanous167e2372018-05-07 11:59:10 -0700166 return 0;
Brad Bishop3d468792016-09-20 15:39:38 -0400167}
168
Ed Tanous167e2372018-05-07 11:59:10 -0700169static int async_wait_getobject_callback(sd_bus_message *m, void *userdata,
170 sd_bus_error *e)
Brad Bishop2afe7182016-08-13 14:08:17 -0400171{
Ed Tanous167e2372018-05-07 11:59:10 -0700172 int i, r;
173 struct async_wait_callback_data *data = userdata;
174 mapper_async_wait *wait = data->wait;
175 uint64_t now;
Brad Bishop2afe7182016-08-13 14:08:17 -0400176
Ed Tanous167e2372018-05-07 11:59:10 -0700177 if (wait->finished)
178 goto exit;
Brad Bishop3d468792016-09-20 15:39:38 -0400179
Ed Tanous167e2372018-05-07 11:59:10 -0700180 r = sd_bus_message_get_errno(m);
181 if (r == ENOENT)
182 goto exit;
Brad Bishop8ccdaed2016-09-20 15:54:32 -0400183
Ed Tanous167e2372018-05-07 11:59:10 -0700184 if (r == EBUSY && data->retry < mapper_busy_retries)
185 {
186 r = sd_event_now(wait->loop, CLOCK_MONOTONIC, &now);
187 if (r < 0)
188 {
189 async_wait_done(r, wait);
190 goto exit;
191 }
Brad Bishop3d468792016-09-20 15:39:38 -0400192
Ed Tanous167e2372018-05-07 11:59:10 -0700193 ++data->retry;
194 r = sd_event_add_time(wait->loop, &data->event_source, CLOCK_MONOTONIC,
195 now + mapper_busy_delay_interval_usec, 0,
196 async_wait_timeout_callback, data);
197 if (r < 0)
198 {
199 async_wait_done(r, wait);
200 goto exit;
201 }
Brad Bishop3d468792016-09-20 15:39:38 -0400202
Ed Tanous167e2372018-05-07 11:59:10 -0700203 return 0;
204 }
Brad Bishop3d468792016-09-20 15:39:38 -0400205
Ed Tanous167e2372018-05-07 11:59:10 -0700206 if (r)
207 {
208 async_wait_done(-r, wait);
209 goto exit;
210 }
Brad Bishop3d468792016-09-20 15:39:38 -0400211
Ed Tanous167e2372018-05-07 11:59:10 -0700212 for (i = 0; i < wait->count; ++i)
213 {
214 if (!strcmp(data->path, wait->objs[i]))
215 {
216 wait->status[i] = 1;
217 }
218 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400219
Ed Tanous167e2372018-05-07 11:59:10 -0700220 if (async_wait_check_done(wait))
221 async_wait_done(0, wait);
Brad Bishop2afe7182016-08-13 14:08:17 -0400222
Brad Bishop3d468792016-09-20 15:39:38 -0400223exit:
Ed Tanous167e2372018-05-07 11:59:10 -0700224 free(data);
225 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400226}
227
228static int async_wait_get_objects(mapper_async_wait *wait)
229{
Ed Tanous167e2372018-05-07 11:59:10 -0700230 int i, r;
231 struct async_wait_callback_data *data = NULL;
Brad Bishop2afe7182016-08-13 14:08:17 -0400232
Ed Tanous167e2372018-05-07 11:59:10 -0700233 for (i = 0; i < wait->count; ++i)
234 {
235 if (wait->status[i])
236 continue;
237 data = malloc(sizeof(*data));
238 data->wait = wait;
239 data->path = wait->objs[i];
240 data->retry = 0;
241 data->event_source = NULL;
242 r = sd_bus_call_method_async(wait->conn, NULL, MAPPER_BUSNAME,
243 MAPPER_PATH, MAPPER_INTERFACE, "GetObject",
244 async_wait_getobject_callback, data, "sas",
245 wait->objs[i], 0, NULL);
246 if (r < 0)
247 {
248 free(data);
249 fprintf(stderr, "Error invoking method: %s\n", strerror(-r));
250 return r;
251 }
252 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400253
Ed Tanous167e2372018-05-07 11:59:10 -0700254 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400255}
256
Brad Bishop829181d2017-02-24 09:49:14 -0500257static int async_wait_match_introspection_complete(sd_bus_message *m, void *w,
Ed Tanous167e2372018-05-07 11:59:10 -0700258 sd_bus_error *e)
Brad Bishop2afe7182016-08-13 14:08:17 -0400259{
Ed Tanous167e2372018-05-07 11:59:10 -0700260 int r;
Brad Bishop2afe7182016-08-13 14:08:17 -0400261
Ed Tanous167e2372018-05-07 11:59:10 -0700262 mapper_async_wait *wait = w;
263 if (wait->finished)
264 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400265
Ed Tanous167e2372018-05-07 11:59:10 -0700266 r = async_wait_get_objects(wait);
267 if (r < 0)
268 async_wait_done(r, wait);
Brad Bishop2afe7182016-08-13 14:08:17 -0400269
Ed Tanous167e2372018-05-07 11:59:10 -0700270 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400271}
272
Brad Bishop2afe7182016-08-13 14:08:17 -0400273static void async_wait_done(int r, mapper_async_wait *w)
274{
Ed Tanous167e2372018-05-07 11:59:10 -0700275 if (w->finished)
276 return;
Brad Bishop2afe7182016-08-13 14:08:17 -0400277
Ed Tanous167e2372018-05-07 11:59:10 -0700278 w->finished = 1;
279 sd_bus_slot_unref(w->introspection_slot);
280 sd_bus_slot_unref(w->intf_slot);
Brad Bishop2afe7182016-08-13 14:08:17 -0400281
Ed Tanous167e2372018-05-07 11:59:10 -0700282 if (w->callback)
283 w->callback(r, w->userdata);
Brad Bishop2afe7182016-08-13 14:08:17 -0400284}
285
286static int async_wait_check_done(mapper_async_wait *w)
287{
Ed Tanous167e2372018-05-07 11:59:10 -0700288 int i;
Brad Bishop2afe7182016-08-13 14:08:17 -0400289
Ed Tanous167e2372018-05-07 11:59:10 -0700290 if (w->finished)
291 return 1;
Brad Bishop2afe7182016-08-13 14:08:17 -0400292
Ed Tanous167e2372018-05-07 11:59:10 -0700293 for (i = 0; i < w->count; ++i)
294 if (!w->status[i])
295 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400296
Ed Tanous167e2372018-05-07 11:59:10 -0700297 return 1;
Brad Bishop2afe7182016-08-13 14:08:17 -0400298}
299
300void mapper_wait_async_free(mapper_async_wait *w)
301{
Ed Tanous167e2372018-05-07 11:59:10 -0700302 free(w->status);
303 sarrayfree(w->objs);
304 free(w);
Brad Bishop2afe7182016-08-13 14:08:17 -0400305}
306
Ed Tanous167e2372018-05-07 11:59:10 -0700307int mapper_wait_async(sd_bus *conn, sd_event *loop, char *objs[],
308 void (*callback)(int, void *), void *userdata,
309 mapper_async_wait **w)
Brad Bishop2afe7182016-08-13 14:08:17 -0400310{
Ed Tanous167e2372018-05-07 11:59:10 -0700311 int r;
312 mapper_async_wait *wait = NULL;
Brad Bishop2afe7182016-08-13 14:08:17 -0400313
Ed Tanous167e2372018-05-07 11:59:10 -0700314 wait = malloc(sizeof(*wait));
315 if (!wait)
316 return -ENOMEM;
Brad Bishop2afe7182016-08-13 14:08:17 -0400317
Ed Tanous167e2372018-05-07 11:59:10 -0700318 memset(wait, 0, sizeof(*wait));
319 wait->conn = conn;
320 wait->loop = loop;
321 wait->callback = callback;
322 wait->userdata = userdata;
323 wait->count = sarraylen(objs);
324 if (!wait->count)
325 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400326
Ed Tanous167e2372018-05-07 11:59:10 -0700327 wait->objs = sarraydup(objs);
328 if (!wait->objs)
329 {
330 r = -ENOMEM;
331 goto free_wait;
332 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400333
Ed Tanous167e2372018-05-07 11:59:10 -0700334 wait->status = malloc(sizeof(*wait->status) * wait->count);
335 if (!wait->status)
336 {
337 r = -ENOMEM;
338 goto free_objs;
339 }
340 memset(wait->status, 0, sizeof(*wait->status) * wait->count);
Brad Bishop2afe7182016-08-13 14:08:17 -0400341
Ed Tanous167e2372018-05-07 11:59:10 -0700342 r = sd_bus_add_match(conn, &wait->introspection_slot,
343 async_wait_introspection_match,
344 async_wait_match_introspection_complete, wait);
345 if (r < 0)
346 {
347 fprintf(stderr, "Error adding match rule: %s\n", strerror(-r));
348 goto free_status;
349 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400350
Ed Tanous167e2372018-05-07 11:59:10 -0700351 r = sd_bus_add_match(conn, &wait->intf_slot,
352 async_wait_interfaces_added_match,
353 async_wait_match_introspection_complete, wait);
354 if (r < 0)
355 {
356 fprintf(stderr, "Error adding match rule: %s\n", strerror(-r));
357 goto unref_name_slot;
358 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400359
Ed Tanous167e2372018-05-07 11:59:10 -0700360 r = async_wait_get_objects(wait);
361 if (r < 0)
362 {
363 fprintf(stderr, "Error calling method: %s\n", strerror(-r));
364 goto unref_intf_slot;
365 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400366
Ed Tanous167e2372018-05-07 11:59:10 -0700367 *w = wait;
Brad Bishop2afe7182016-08-13 14:08:17 -0400368
Ed Tanous167e2372018-05-07 11:59:10 -0700369 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400370
371unref_intf_slot:
Ed Tanous167e2372018-05-07 11:59:10 -0700372 sd_bus_slot_unref(wait->intf_slot);
Brad Bishop2afe7182016-08-13 14:08:17 -0400373unref_name_slot:
Ed Tanous167e2372018-05-07 11:59:10 -0700374 sd_bus_slot_unref(wait->introspection_slot);
Brad Bishop2afe7182016-08-13 14:08:17 -0400375free_status:
Ed Tanous167e2372018-05-07 11:59:10 -0700376 free(wait->status);
Brad Bishop2afe7182016-08-13 14:08:17 -0400377free_objs:
Ed Tanous167e2372018-05-07 11:59:10 -0700378 sarrayfree(wait->objs);
Brad Bishop2afe7182016-08-13 14:08:17 -0400379free_wait:
Ed Tanous167e2372018-05-07 11:59:10 -0700380 free(wait);
Brad Bishop2afe7182016-08-13 14:08:17 -0400381
Ed Tanous167e2372018-05-07 11:59:10 -0700382 return r;
Brad Bishop2afe7182016-08-13 14:08:17 -0400383}
384
Ed Tanous167e2372018-05-07 11:59:10 -0700385static int async_subtree_timeout_callback(sd_event_source *s, uint64_t usec,
386 void *userdata)
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500387{
Ed Tanous167e2372018-05-07 11:59:10 -0700388 int r;
389 struct mapper_async_subtree *subtree = userdata;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500390
Ed Tanous167e2372018-05-07 11:59:10 -0700391 sd_event_source_unref(subtree->event_source);
392 r = sd_bus_call_method_async(
393 subtree->conn, NULL, MAPPER_BUSNAME, MAPPER_PATH, MAPPER_INTERFACE,
394 "GetSubTreePaths", async_subtree_getpaths_callback, subtree, "sias",
395 subtree->namespace, 0, 1, subtree->interface);
396 if (r < 0)
397 async_subtree_done(r, subtree);
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500398
Ed Tanous167e2372018-05-07 11:59:10 -0700399 return 0;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500400}
401
Ed Tanous167e2372018-05-07 11:59:10 -0700402static int async_subtree_getpaths_callback(sd_bus_message *m, void *userdata,
403 sd_bus_error *e)
Adriana Kobylak025d7952017-05-08 13:30:45 -0500404{
Ed Tanous167e2372018-05-07 11:59:10 -0700405 int r;
406 char *intf = NULL;
407 struct mapper_async_subtree *subtree = userdata;
408 uint64_t now;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500409
Ed Tanous167e2372018-05-07 11:59:10 -0700410 if (subtree->finished)
411 goto exit;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500412
Ed Tanous167e2372018-05-07 11:59:10 -0700413 r = sd_bus_message_get_errno(m);
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500414
Ed Tanous167e2372018-05-07 11:59:10 -0700415 if (r == ENOENT)
416 {
417 if (subtree->op == MAPPER_OP_REMOVE)
418 r = 0;
419 else
420 goto exit;
421 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500422
Ed Tanous167e2372018-05-07 11:59:10 -0700423 if (r == EBUSY && subtree->retry < mapper_busy_retries)
424 {
425 r = sd_event_now(subtree->loop, CLOCK_MONOTONIC, &now);
426 if (r < 0)
427 {
428 async_subtree_done(r, subtree);
429 goto exit;
430 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500431
Ed Tanous167e2372018-05-07 11:59:10 -0700432 ++subtree->retry;
433 r = sd_event_add_time(subtree->loop, &subtree->event_source,
434 CLOCK_MONOTONIC,
435 now + mapper_busy_delay_interval_usec, 0,
436 async_subtree_timeout_callback, subtree);
437 if (r < 0)
438 {
439 async_subtree_done(r, subtree);
440 goto exit;
441 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500442
Ed Tanous167e2372018-05-07 11:59:10 -0700443 return 0;
444 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500445
Ed Tanous167e2372018-05-07 11:59:10 -0700446 if (r)
447 {
448 async_subtree_done(-r, subtree);
449 goto exit;
450 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500451
Ed Tanous167e2372018-05-07 11:59:10 -0700452 sd_bus_message_read(m, "as", 1, &intf);
453 if (subtree->op == MAPPER_OP_REMOVE)
454 {
455 /* For remove, operation is complete when the interface is not present
456 */
457 if (intf == NULL)
458 async_subtree_done(0, subtree);
459 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500460
461exit:
Ed Tanous167e2372018-05-07 11:59:10 -0700462 return 0;
Adriana Kobylak025d7952017-05-08 13:30:45 -0500463}
464
465static int async_subtree_getpaths(mapper_async_subtree *subtree)
466{
Ed Tanous167e2372018-05-07 11:59:10 -0700467 int r = 0;
Adriana Kobylak025d7952017-05-08 13:30:45 -0500468
Ed Tanous167e2372018-05-07 11:59:10 -0700469 subtree->retry = 0;
470 subtree->event_source = NULL;
471 r = sd_bus_call_method_async(
472 subtree->conn, NULL, MAPPER_BUSNAME, MAPPER_PATH, MAPPER_INTERFACE,
473 "GetSubTreePaths", async_subtree_getpaths_callback, subtree, "sias",
474 subtree->namespace, 0, 1, subtree->interface);
475 if (r < 0)
476 {
477 fprintf(stderr, "Error invoking method: %s\n", strerror(-r));
478 return r;
479 }
Adriana Kobylak025d7952017-05-08 13:30:45 -0500480
Ed Tanous167e2372018-05-07 11:59:10 -0700481 return 0;
Adriana Kobylak025d7952017-05-08 13:30:45 -0500482}
483
Ed Tanous167e2372018-05-07 11:59:10 -0700484static int async_subtree_match_callback(sd_bus_message *m, void *t,
485 sd_bus_error *e)
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500486{
Ed Tanous167e2372018-05-07 11:59:10 -0700487 int r;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500488
Ed Tanous167e2372018-05-07 11:59:10 -0700489 mapper_async_subtree *subtree = t;
490 if (subtree->finished)
491 return 0;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500492
Ed Tanous167e2372018-05-07 11:59:10 -0700493 r = async_subtree_getpaths(subtree);
494 if (r < 0)
495 async_subtree_done(r, subtree);
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500496
Ed Tanous167e2372018-05-07 11:59:10 -0700497 return 0;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500498}
499
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500500static void async_subtree_done(int r, mapper_async_subtree *t)
501{
Ed Tanous167e2372018-05-07 11:59:10 -0700502 if (t->finished)
503 return;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500504
Ed Tanous167e2372018-05-07 11:59:10 -0700505 t->finished = 1;
506 sd_bus_slot_unref(t->slot);
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500507
Ed Tanous167e2372018-05-07 11:59:10 -0700508 if (t->callback)
509 t->callback(r, t->userdata);
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500510}
511
Ed Tanous167e2372018-05-07 11:59:10 -0700512int mapper_subtree_async(sd_bus *conn, sd_event *loop, char *namespace,
513 char *interface, void (*callback)(int, void *),
514 void *userdata, mapper_async_subtree **t, int op)
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500515{
Ed Tanous167e2372018-05-07 11:59:10 -0700516 int r = 0;
517 mapper_async_subtree *subtree = NULL;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500518
Ed Tanous167e2372018-05-07 11:59:10 -0700519 subtree = malloc(sizeof(*subtree));
520 if (!subtree)
521 return -ENOMEM;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500522
Ed Tanous167e2372018-05-07 11:59:10 -0700523 memset(subtree, 0, sizeof(*subtree));
524 subtree->conn = conn;
525 subtree->loop = loop;
526 subtree->namespace = namespace;
527 subtree->interface = interface;
528 subtree->callback = callback;
529 subtree->userdata = userdata;
530 subtree->op = op;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500531
Ed Tanous167e2372018-05-07 11:59:10 -0700532 if (subtree->op == MAPPER_OP_REMOVE)
533 {
534 r = sd_bus_add_match(conn, &subtree->slot, interfaces_removed_match,
535 async_subtree_match_callback, subtree);
536 if (r < 0)
537 {
538 fprintf(stderr, "Error adding match rule: %s\n", strerror(-r));
539 goto unref_slot;
540 }
541 }
542 else
543 {
544 /* Operation not supported */
545 r = -EINVAL;
546 goto free_subtree;
547 }
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500548
Ed Tanous167e2372018-05-07 11:59:10 -0700549 r = async_subtree_getpaths(subtree);
550 if (r < 0)
551 {
552 fprintf(stderr, "Error calling method: %s\n", strerror(-r));
553 goto unref_slot;
554 }
Adriana Kobylak025d7952017-05-08 13:30:45 -0500555
Ed Tanous167e2372018-05-07 11:59:10 -0700556 *t = subtree;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500557
Ed Tanous167e2372018-05-07 11:59:10 -0700558 return 0;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500559
560unref_slot:
Ed Tanous167e2372018-05-07 11:59:10 -0700561 sd_bus_slot_unref(subtree->slot);
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500562free_subtree:
Ed Tanous167e2372018-05-07 11:59:10 -0700563 free(subtree);
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500564
Ed Tanous167e2372018-05-07 11:59:10 -0700565 return r;
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500566}
567
Brad Bishop3d468792016-09-20 15:39:38 -0400568int mapper_get_object(sd_bus *conn, const char *obj, sd_bus_message **reply)
Brad Bishop62ece2b2016-07-25 09:00:51 -0400569{
Ed Tanous167e2372018-05-07 11:59:10 -0700570 sd_bus_error error = SD_BUS_ERROR_NULL;
571 sd_bus_message *request = NULL;
572 int r, retry = 0;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400573
Ed Tanous167e2372018-05-07 11:59:10 -0700574 r = sd_bus_message_new_method_call(conn, &request, MAPPER_BUSNAME,
575 MAPPER_PATH, MAPPER_INTERFACE,
576 "GetObject");
577 if (r < 0)
578 goto exit;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400579
Ed Tanous167e2372018-05-07 11:59:10 -0700580 r = sd_bus_message_append(request, "s", obj);
581 if (r < 0)
582 goto exit;
583 r = sd_bus_message_append(request, "as", 0, NULL);
584 if (r < 0)
585 goto exit;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400586
Ed Tanous167e2372018-05-07 11:59:10 -0700587 while (retry < mapper_busy_retries)
588 {
589 sd_bus_error_free(&error);
590 r = sd_bus_call(conn, request, 0, &error, reply);
591 if (r < 0 && sd_bus_error_get_errno(&error) == EBUSY)
592 {
593 ++retry;
Brad Bishop3d468792016-09-20 15:39:38 -0400594
Ed Tanous167e2372018-05-07 11:59:10 -0700595 if (retry != mapper_busy_retries)
596 usleep(mapper_busy_delay_interval_usec);
597 continue;
598 }
599 break;
600 }
Brad Bishop3d468792016-09-20 15:39:38 -0400601
Ed Tanous167e2372018-05-07 11:59:10 -0700602 if (r < 0)
603 goto exit;
Brad Bishop3d468792016-09-20 15:39:38 -0400604
605exit:
Ed Tanous167e2372018-05-07 11:59:10 -0700606 sd_bus_error_free(&error);
607 sd_bus_message_unref(request);
Brad Bishop3d468792016-09-20 15:39:38 -0400608
Ed Tanous167e2372018-05-07 11:59:10 -0700609 return r;
Brad Bishop3d468792016-09-20 15:39:38 -0400610}
611
612int mapper_get_service(sd_bus *conn, const char *obj, char **service)
613{
Ed Tanous167e2372018-05-07 11:59:10 -0700614 sd_bus_message *reply = NULL;
615 const char *tmp;
616 int r;
Brad Bishop3d468792016-09-20 15:39:38 -0400617
Ed Tanous167e2372018-05-07 11:59:10 -0700618 r = mapper_get_object(conn, obj, &reply);
619 if (r < 0)
620 goto exit;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400621
Ed Tanous167e2372018-05-07 11:59:10 -0700622 r = sd_bus_message_enter_container(reply, 0, NULL);
623 if (r < 0)
624 goto exit;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400625
Ed Tanous167e2372018-05-07 11:59:10 -0700626 r = sd_bus_message_enter_container(reply, 0, NULL);
627 if (r < 0)
628 goto exit;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400629
Ed Tanous167e2372018-05-07 11:59:10 -0700630 r = sd_bus_message_read(reply, "s", &tmp);
631 if (r < 0)
632 goto exit;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400633
Ed Tanous167e2372018-05-07 11:59:10 -0700634 *service = strdup(tmp);
Brad Bishop62ece2b2016-07-25 09:00:51 -0400635
636exit:
Ed Tanous167e2372018-05-07 11:59:10 -0700637 sd_bus_message_unref(reply);
Brad Bishop62ece2b2016-07-25 09:00:51 -0400638
Ed Tanous167e2372018-05-07 11:59:10 -0700639 return r;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400640}