blob: 4a1cd3beb85e718644f521875e8f5c046539aa46 [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"
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050017
18#include "mapper.h"
19
20#include <errno.h>
William A. Kennington III20cbbfb2018-06-15 10:10:13 -070021#include <stdbool.h>
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050022#include <stdio.h>
Brad Bishop2afe7182016-08-13 14:08:17 -040023#include <stdlib.h>
Brad Bishop62ece2b2016-07-25 09:00:51 -040024#include <string.h>
Brad Bishop3d468792016-09-20 15:39:38 -040025#include <sys/timerfd.h>
Brad Bishop62ece2b2016-07-25 09:00:51 -040026#include <systemd/sd-bus.h>
Brad Bishop3d468792016-09-20 15:39:38 -040027#include <systemd/sd-event.h>
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050028#include <unistd.h>
Brad Bishop62ece2b2016-07-25 09:00:51 -040029
Brad Bishopa669a502021-08-03 16:01:43 -040030#include "internal.h"
31
Brad Bishop75057c82021-08-03 15:22:02 -040032#define _public_ __attribute__((__visibility__("default")))
33
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050034static const char* async_wait_introspection_match =
Ed Tanous167e2372018-05-07 11:59:10 -070035 "type='signal',"
36 "sender='xyz.openbmc_project.ObjectMapper',"
37 "interface='xyz.openbmc_project.ObjectMapper.Private',"
38 "member='IntrospectionComplete'";
Brad Bishop2afe7182016-08-13 14:08:17 -040039
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050040static const char* async_wait_interfaces_added_match =
Ed Tanous167e2372018-05-07 11:59:10 -070041 "type='signal',"
42 "interface='org.freedesktop.DBus.ObjectManager',"
43 "member='InterfacesAdded'";
Brad Bishop2afe7182016-08-13 14:08:17 -040044
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050045static const char* interfaces_removed_match =
Ed Tanous167e2372018-05-07 11:59:10 -070046 "type='signal',"
47 "interface='org.freedesktop.DBus.ObjectManager',"
48 "member='InterfacesRemoved'";
Adriana Kobylak78edbb62017-05-04 15:45:19 -050049
Brad Bishop3d468792016-09-20 15:39:38 -040050static const int mapper_busy_retries = 5;
51static const uint64_t mapper_busy_delay_interval_usec = 1000000;
52
Brad Bishop2afe7182016-08-13 14:08:17 -040053struct mapper_async_wait
54{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050055 char** objs;
56 void (*callback)(int, void*);
57 void* userdata;
58 sd_event* loop;
59 sd_bus* conn;
60 sd_bus_slot* introspection_slot;
61 sd_bus_slot* intf_slot;
62 int* status;
Ed Tanous167e2372018-05-07 11:59:10 -070063 int count;
64 int finished;
65 int r;
Brad Bishop2afe7182016-08-13 14:08:17 -040066};
67
68struct async_wait_callback_data
69{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050070 mapper_async_wait* wait;
71 const char* path;
72 sd_event_source* event_source;
Ed Tanous167e2372018-05-07 11:59:10 -070073 int retry;
Brad Bishop2afe7182016-08-13 14:08:17 -040074};
75
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -050076struct mapper_async_subtree
77{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050078 char* namespace;
79 char* interface;
80 void (*callback)(int, void*);
81 void* userdata;
82 sd_event* loop;
83 sd_bus* conn;
84 sd_bus_slot* slot;
85 sd_event_source* event_source;
Ed Tanous167e2372018-05-07 11:59:10 -070086 int finished;
87 int op;
88 int retry;
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -050089};
90
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050091static int async_wait_match_introspection_complete(sd_bus_message*, void*,
92 sd_bus_error*);
93static int async_wait_check_done(mapper_async_wait*);
94static void async_wait_done(int r, mapper_async_wait*);
95static int async_wait_get_objects(mapper_async_wait*);
96static int async_wait_getobject_callback(sd_bus_message*, void*, sd_bus_error*);
Brad Bishop2afe7182016-08-13 14:08:17 -040097
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050098static int async_subtree_match_callback(sd_bus_message*, void*, sd_bus_error*);
99static void async_subtree_done(int r, mapper_async_subtree*);
100static int async_subtree_getpaths(mapper_async_subtree*);
101static int async_subtree_getpaths_callback(sd_bus_message*, void*,
102 sd_bus_error*);
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500103
Brad Bishopa669a502021-08-03 16:01:43 -0400104int sarraylen(char* array[])
Brad Bishop2afe7182016-08-13 14:08:17 -0400105{
Ed Tanous167e2372018-05-07 11:59:10 -0700106 int count = 0;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500107 char** p = array;
Brad Bishop2afe7182016-08-13 14:08:17 -0400108
Ed Tanous167e2372018-05-07 11:59:10 -0700109 while (*p != NULL)
110 {
111 ++count;
112 ++p;
113 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400114
Ed Tanous167e2372018-05-07 11:59:10 -0700115 return count;
Brad Bishop2afe7182016-08-13 14:08:17 -0400116}
117
Brad Bishopa669a502021-08-03 16:01:43 -0400118void sarrayfree(char* array[])
Brad Bishop2afe7182016-08-13 14:08:17 -0400119{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500120 char** p = array;
Ed Tanous167e2372018-05-07 11:59:10 -0700121 while (*p != NULL)
122 {
123 free(*p);
124 ++p;
125 }
126 free(array);
Brad Bishop2afe7182016-08-13 14:08:17 -0400127}
128
Brad Bishopa669a502021-08-03 16:01:43 -0400129char** sarraydup(char* array[])
Brad Bishop2afe7182016-08-13 14:08:17 -0400130{
Ed Tanous167e2372018-05-07 11:59:10 -0700131 int count = sarraylen(array);
132 int i;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500133 char** ret = NULL;
Brad Bishop2afe7182016-08-13 14:08:17 -0400134
Brad Bishopa669a502021-08-03 16:01:43 -0400135 ret = calloc(count + 1, sizeof(*ret));
Ed Tanous167e2372018-05-07 11:59:10 -0700136 if (!ret)
137 return NULL;
Brad Bishop2afe7182016-08-13 14:08:17 -0400138
Ed Tanous167e2372018-05-07 11:59:10 -0700139 for (i = 0; i < count; ++i)
140 {
141 ret[i] = strdup(array[i]);
142 if (!ret[i])
143 goto error;
144 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400145
Ed Tanous167e2372018-05-07 11:59:10 -0700146 return ret;
Brad Bishop2afe7182016-08-13 14:08:17 -0400147
148error:
Ed Tanous167e2372018-05-07 11:59:10 -0700149 sarrayfree(ret);
150 return NULL;
Brad Bishop2afe7182016-08-13 14:08:17 -0400151}
152
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500153static int async_wait_timeout_callback(sd_event_source* s, uint64_t usec,
154 void* userdata)
Brad Bishop3d468792016-09-20 15:39:38 -0400155{
Ed Tanous167e2372018-05-07 11:59:10 -0700156 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500157 struct async_wait_callback_data* data = userdata;
158 mapper_async_wait* wait = data->wait;
Brad Bishop3d468792016-09-20 15:39:38 -0400159
Ed Tanous167e2372018-05-07 11:59:10 -0700160 sd_event_source_unref(data->event_source);
161 r = sd_bus_call_method_async(wait->conn, NULL, MAPPER_BUSNAME, MAPPER_PATH,
162 MAPPER_INTERFACE, "GetObject",
163 async_wait_getobject_callback, data, "sas",
164 data->path, 0, NULL);
165 if (r < 0)
166 {
167 async_wait_done(r, wait);
168 free(data);
169 }
Brad Bishop3d468792016-09-20 15:39:38 -0400170
Ed Tanous167e2372018-05-07 11:59:10 -0700171 return 0;
Brad Bishop3d468792016-09-20 15:39:38 -0400172}
173
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500174static int async_wait_getobject_callback(sd_bus_message* m, void* userdata,
175 sd_bus_error* e)
Brad Bishop2afe7182016-08-13 14:08:17 -0400176{
Ed Tanous167e2372018-05-07 11:59:10 -0700177 int i, r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500178 struct async_wait_callback_data* data = userdata;
179 mapper_async_wait* wait = data->wait;
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700180 uint64_t next_retry;
Brad Bishop2afe7182016-08-13 14:08:17 -0400181
Ed Tanous167e2372018-05-07 11:59:10 -0700182 if (wait->finished)
183 goto exit;
Brad Bishop3d468792016-09-20 15:39:38 -0400184
Patrick Williamse82b0582020-11-16 16:25:20 -0600185 if (sd_bus_message_is_method_error(
186 m, "xyz.openbmc_project.Common.Error.ResourceNotFound"))
Ed Tanous167e2372018-05-07 11:59:10 -0700187 goto exit;
Brad Bishop8ccdaed2016-09-20 15:54:32 -0400188
Patrick Williamse82b0582020-11-16 16:25:20 -0600189 r = sd_bus_message_get_errno(m);
190
William A. Kennington III24829462018-06-15 10:10:25 -0700191 if ((r == EBUSY || r == ENOBUFS) && data->retry < mapper_busy_retries)
Ed Tanous167e2372018-05-07 11:59:10 -0700192 {
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700193 r = sd_event_now(wait->loop, CLOCK_MONOTONIC, &next_retry);
Ed Tanous167e2372018-05-07 11:59:10 -0700194 if (r < 0)
195 {
196 async_wait_done(r, wait);
197 goto exit;
198 }
Brad Bishop3d468792016-09-20 15:39:38 -0400199
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700200 next_retry += mapper_busy_delay_interval_usec * (1 << data->retry);
Ed Tanous167e2372018-05-07 11:59:10 -0700201 r = sd_event_add_time(wait->loop, &data->event_source, CLOCK_MONOTONIC,
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700202 next_retry, 0, async_wait_timeout_callback, data);
203 ++data->retry;
Ed Tanous167e2372018-05-07 11:59:10 -0700204 if (r < 0)
205 {
206 async_wait_done(r, wait);
207 goto exit;
208 }
Brad Bishop3d468792016-09-20 15:39:38 -0400209
Ed Tanous167e2372018-05-07 11:59:10 -0700210 return 0;
211 }
Brad Bishop3d468792016-09-20 15:39:38 -0400212
Ed Tanous167e2372018-05-07 11:59:10 -0700213 if (r)
214 {
215 async_wait_done(-r, wait);
216 goto exit;
217 }
Brad Bishop3d468792016-09-20 15:39:38 -0400218
Ed Tanous167e2372018-05-07 11:59:10 -0700219 for (i = 0; i < wait->count; ++i)
220 {
221 if (!strcmp(data->path, wait->objs[i]))
222 {
223 wait->status[i] = 1;
224 }
225 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400226
Ed Tanous167e2372018-05-07 11:59:10 -0700227 if (async_wait_check_done(wait))
228 async_wait_done(0, wait);
Brad Bishop2afe7182016-08-13 14:08:17 -0400229
Brad Bishop3d468792016-09-20 15:39:38 -0400230exit:
Ed Tanous167e2372018-05-07 11:59:10 -0700231 free(data);
232 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400233}
234
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500235static int async_wait_get_objects(mapper_async_wait* wait)
Brad Bishop2afe7182016-08-13 14:08:17 -0400236{
Ed Tanous167e2372018-05-07 11:59:10 -0700237 int i, r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500238 struct async_wait_callback_data* data = NULL;
Brad Bishop2afe7182016-08-13 14:08:17 -0400239
Ed Tanous167e2372018-05-07 11:59:10 -0700240 for (i = 0; i < wait->count; ++i)
241 {
242 if (wait->status[i])
243 continue;
244 data = malloc(sizeof(*data));
245 data->wait = wait;
246 data->path = wait->objs[i];
247 data->retry = 0;
248 data->event_source = NULL;
249 r = sd_bus_call_method_async(wait->conn, NULL, MAPPER_BUSNAME,
250 MAPPER_PATH, MAPPER_INTERFACE, "GetObject",
251 async_wait_getobject_callback, data, "sas",
252 wait->objs[i], 0, NULL);
253 if (r < 0)
254 {
255 free(data);
256 fprintf(stderr, "Error invoking method: %s\n", strerror(-r));
257 return r;
258 }
259 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400260
Ed Tanous167e2372018-05-07 11:59:10 -0700261 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400262}
263
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500264static int async_wait_match_introspection_complete(sd_bus_message* m, void* w,
265 sd_bus_error* e)
Brad Bishop2afe7182016-08-13 14:08:17 -0400266{
Ed Tanous167e2372018-05-07 11:59:10 -0700267 int r;
Brad Bishop2afe7182016-08-13 14:08:17 -0400268
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500269 mapper_async_wait* wait = w;
Ed Tanous167e2372018-05-07 11:59:10 -0700270 if (wait->finished)
271 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400272
Ed Tanous167e2372018-05-07 11:59:10 -0700273 r = async_wait_get_objects(wait);
274 if (r < 0)
275 async_wait_done(r, wait);
Brad Bishop2afe7182016-08-13 14:08:17 -0400276
Ed Tanous167e2372018-05-07 11:59:10 -0700277 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400278}
279
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500280static void async_wait_done(int r, mapper_async_wait* w)
Brad Bishop2afe7182016-08-13 14:08:17 -0400281{
Ed Tanous167e2372018-05-07 11:59:10 -0700282 if (w->finished)
283 return;
Brad Bishop2afe7182016-08-13 14:08:17 -0400284
Ed Tanous167e2372018-05-07 11:59:10 -0700285 w->finished = 1;
286 sd_bus_slot_unref(w->introspection_slot);
287 sd_bus_slot_unref(w->intf_slot);
Brad Bishop2afe7182016-08-13 14:08:17 -0400288
Ed Tanous167e2372018-05-07 11:59:10 -0700289 if (w->callback)
290 w->callback(r, w->userdata);
Brad Bishop2afe7182016-08-13 14:08:17 -0400291}
292
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500293static int async_wait_check_done(mapper_async_wait* w)
Brad Bishop2afe7182016-08-13 14:08:17 -0400294{
Ed Tanous167e2372018-05-07 11:59:10 -0700295 int i;
Brad Bishop2afe7182016-08-13 14:08:17 -0400296
Ed Tanous167e2372018-05-07 11:59:10 -0700297 if (w->finished)
298 return 1;
Brad Bishop2afe7182016-08-13 14:08:17 -0400299
Ed Tanous167e2372018-05-07 11:59:10 -0700300 for (i = 0; i < w->count; ++i)
301 if (!w->status[i])
302 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400303
Ed Tanous167e2372018-05-07 11:59:10 -0700304 return 1;
Brad Bishop2afe7182016-08-13 14:08:17 -0400305}
306
Brad Bishop75057c82021-08-03 15:22:02 -0400307_public_ void mapper_wait_async_free(mapper_async_wait* w)
Brad Bishop2afe7182016-08-13 14:08:17 -0400308{
Ed Tanous167e2372018-05-07 11:59:10 -0700309 free(w->status);
310 sarrayfree(w->objs);
311 free(w);
Brad Bishop2afe7182016-08-13 14:08:17 -0400312}
313
Brad Bishop75057c82021-08-03 15:22:02 -0400314_public_ int mapper_wait_async(sd_bus* conn, sd_event* loop, char* objs[],
315 void (*callback)(int, void*), void* userdata,
316 mapper_async_wait** w)
Brad Bishop2afe7182016-08-13 14:08:17 -0400317{
Ed Tanous167e2372018-05-07 11:59:10 -0700318 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500319 mapper_async_wait* wait = NULL;
Brad Bishop2afe7182016-08-13 14:08:17 -0400320
Ed Tanous167e2372018-05-07 11:59:10 -0700321 wait = malloc(sizeof(*wait));
322 if (!wait)
323 return -ENOMEM;
Brad Bishop2afe7182016-08-13 14:08:17 -0400324
Ed Tanous167e2372018-05-07 11:59:10 -0700325 memset(wait, 0, sizeof(*wait));
326 wait->conn = conn;
327 wait->loop = loop;
328 wait->callback = callback;
329 wait->userdata = userdata;
330 wait->count = sarraylen(objs);
331 if (!wait->count)
332 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400333
Ed Tanous167e2372018-05-07 11:59:10 -0700334 wait->objs = sarraydup(objs);
335 if (!wait->objs)
336 {
337 r = -ENOMEM;
338 goto free_wait;
339 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400340
Ed Tanous167e2372018-05-07 11:59:10 -0700341 wait->status = malloc(sizeof(*wait->status) * wait->count);
342 if (!wait->status)
343 {
344 r = -ENOMEM;
345 goto free_objs;
346 }
347 memset(wait->status, 0, sizeof(*wait->status) * wait->count);
Brad Bishop2afe7182016-08-13 14:08:17 -0400348
Ed Tanous167e2372018-05-07 11:59:10 -0700349 r = sd_bus_add_match(conn, &wait->introspection_slot,
350 async_wait_introspection_match,
351 async_wait_match_introspection_complete, wait);
352 if (r < 0)
353 {
354 fprintf(stderr, "Error adding match rule: %s\n", strerror(-r));
355 goto free_status;
356 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400357
Ed Tanous167e2372018-05-07 11:59:10 -0700358 r = sd_bus_add_match(conn, &wait->intf_slot,
359 async_wait_interfaces_added_match,
360 async_wait_match_introspection_complete, wait);
361 if (r < 0)
362 {
363 fprintf(stderr, "Error adding match rule: %s\n", strerror(-r));
364 goto unref_name_slot;
365 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400366
Ed Tanous167e2372018-05-07 11:59:10 -0700367 r = async_wait_get_objects(wait);
368 if (r < 0)
369 {
370 fprintf(stderr, "Error calling method: %s\n", strerror(-r));
371 goto unref_intf_slot;
372 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400373
Ed Tanous167e2372018-05-07 11:59:10 -0700374 *w = wait;
Brad Bishop2afe7182016-08-13 14:08:17 -0400375
Ed Tanous167e2372018-05-07 11:59:10 -0700376 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400377
378unref_intf_slot:
Ed Tanous167e2372018-05-07 11:59:10 -0700379 sd_bus_slot_unref(wait->intf_slot);
Brad Bishop2afe7182016-08-13 14:08:17 -0400380unref_name_slot:
Ed Tanous167e2372018-05-07 11:59:10 -0700381 sd_bus_slot_unref(wait->introspection_slot);
Brad Bishop2afe7182016-08-13 14:08:17 -0400382free_status:
Ed Tanous167e2372018-05-07 11:59:10 -0700383 free(wait->status);
Brad Bishop2afe7182016-08-13 14:08:17 -0400384free_objs:
Ed Tanous167e2372018-05-07 11:59:10 -0700385 sarrayfree(wait->objs);
Brad Bishop2afe7182016-08-13 14:08:17 -0400386free_wait:
Ed Tanous167e2372018-05-07 11:59:10 -0700387 free(wait);
Brad Bishop2afe7182016-08-13 14:08:17 -0400388
Ed Tanous167e2372018-05-07 11:59:10 -0700389 return r;
Brad Bishop2afe7182016-08-13 14:08:17 -0400390}
391
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500392static int async_subtree_timeout_callback(sd_event_source* s, uint64_t usec,
393 void* userdata)
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500394{
Ed Tanous167e2372018-05-07 11:59:10 -0700395 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500396 struct mapper_async_subtree* subtree = userdata;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500397
Ed Tanous167e2372018-05-07 11:59:10 -0700398 sd_event_source_unref(subtree->event_source);
399 r = sd_bus_call_method_async(
400 subtree->conn, NULL, MAPPER_BUSNAME, MAPPER_PATH, MAPPER_INTERFACE,
401 "GetSubTreePaths", async_subtree_getpaths_callback, subtree, "sias",
402 subtree->namespace, 0, 1, subtree->interface);
403 if (r < 0)
404 async_subtree_done(r, subtree);
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500405
Ed Tanous167e2372018-05-07 11:59:10 -0700406 return 0;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500407}
408
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500409static int async_subtree_getpaths_callback(sd_bus_message* m, void* userdata,
410 sd_bus_error* e)
Adriana Kobylak025d7952017-05-08 13:30:45 -0500411{
Ed Tanous167e2372018-05-07 11:59:10 -0700412 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500413 struct mapper_async_subtree* subtree = userdata;
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700414 uint64_t next_retry;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500415
Ed Tanous167e2372018-05-07 11:59:10 -0700416 if (subtree->finished)
417 goto exit;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500418
Ed Tanous167e2372018-05-07 11:59:10 -0700419 r = sd_bus_message_get_errno(m);
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500420
Patrick Williamse82b0582020-11-16 16:25:20 -0600421 if (sd_bus_message_is_method_error(
422 m, "xyz.openbmc_project.Common.Error.ResourceNotFound"))
Ed Tanous167e2372018-05-07 11:59:10 -0700423 {
424 if (subtree->op == MAPPER_OP_REMOVE)
425 r = 0;
426 else
427 goto exit;
428 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500429
William A. Kennington III24829462018-06-15 10:10:25 -0700430 if ((r == EBUSY || r == ENOBUFS) && subtree->retry < mapper_busy_retries)
Ed Tanous167e2372018-05-07 11:59:10 -0700431 {
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700432 r = sd_event_now(subtree->loop, CLOCK_MONOTONIC, &next_retry);
Ed Tanous167e2372018-05-07 11:59:10 -0700433 if (r < 0)
434 {
435 async_subtree_done(r, subtree);
436 goto exit;
437 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500438
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700439 next_retry += mapper_busy_delay_interval_usec * (1 << subtree->retry);
Ed Tanous167e2372018-05-07 11:59:10 -0700440 r = sd_event_add_time(subtree->loop, &subtree->event_source,
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700441 CLOCK_MONOTONIC, next_retry, 0,
Ed Tanous167e2372018-05-07 11:59:10 -0700442 async_subtree_timeout_callback, subtree);
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700443 ++subtree->retry;
Ed Tanous167e2372018-05-07 11:59:10 -0700444 if (r < 0)
445 {
446 async_subtree_done(r, subtree);
447 goto exit;
448 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500449
Ed Tanous167e2372018-05-07 11:59:10 -0700450 return 0;
451 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500452
Ed Tanous167e2372018-05-07 11:59:10 -0700453 if (r)
454 {
455 async_subtree_done(-r, subtree);
456 goto exit;
457 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500458
Ed Tanous167e2372018-05-07 11:59:10 -0700459 if (subtree->op == MAPPER_OP_REMOVE)
460 {
William A. Kennington III20cbbfb2018-06-15 10:10:13 -0700461 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "s");
462 if (r < 0)
463 {
464 async_subtree_done(r, subtree);
465 goto exit;
466 }
467
468 r = sd_bus_message_at_end(m, false);
469 if (r < 0)
470 {
471 async_subtree_done(r, subtree);
472 goto exit;
473 }
474
Ed Tanous167e2372018-05-07 11:59:10 -0700475 /* For remove, operation is complete when the interface is not present
William A. Kennington III20cbbfb2018-06-15 10:10:13 -0700476 * we know it is empty if the returned array is empty
Ed Tanous167e2372018-05-07 11:59:10 -0700477 */
William A. Kennington III20cbbfb2018-06-15 10:10:13 -0700478 if (r)
Ed Tanous167e2372018-05-07 11:59:10 -0700479 async_subtree_done(0, subtree);
480 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500481
482exit:
Ed Tanous167e2372018-05-07 11:59:10 -0700483 return 0;
Adriana Kobylak025d7952017-05-08 13:30:45 -0500484}
485
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500486static int async_subtree_getpaths(mapper_async_subtree* subtree)
Adriana Kobylak025d7952017-05-08 13:30:45 -0500487{
Ed Tanous167e2372018-05-07 11:59:10 -0700488 int r = 0;
Adriana Kobylak025d7952017-05-08 13:30:45 -0500489
Ed Tanous167e2372018-05-07 11:59:10 -0700490 subtree->retry = 0;
491 subtree->event_source = NULL;
492 r = sd_bus_call_method_async(
493 subtree->conn, NULL, MAPPER_BUSNAME, MAPPER_PATH, MAPPER_INTERFACE,
494 "GetSubTreePaths", async_subtree_getpaths_callback, subtree, "sias",
495 subtree->namespace, 0, 1, subtree->interface);
496 if (r < 0)
497 {
498 fprintf(stderr, "Error invoking method: %s\n", strerror(-r));
499 return r;
500 }
Adriana Kobylak025d7952017-05-08 13:30:45 -0500501
Ed Tanous167e2372018-05-07 11:59:10 -0700502 return 0;
Adriana Kobylak025d7952017-05-08 13:30:45 -0500503}
504
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500505static int async_subtree_match_callback(sd_bus_message* m, void* t,
506 sd_bus_error* e)
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500507{
Ed Tanous167e2372018-05-07 11:59:10 -0700508 int r;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500509
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500510 mapper_async_subtree* subtree = t;
Ed Tanous167e2372018-05-07 11:59:10 -0700511 if (subtree->finished)
512 return 0;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500513
Ed Tanous167e2372018-05-07 11:59:10 -0700514 r = async_subtree_getpaths(subtree);
515 if (r < 0)
516 async_subtree_done(r, subtree);
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500517
Ed Tanous167e2372018-05-07 11:59:10 -0700518 return 0;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500519}
520
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500521static void async_subtree_done(int r, mapper_async_subtree* t)
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500522{
Ed Tanous167e2372018-05-07 11:59:10 -0700523 if (t->finished)
524 return;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500525
Ed Tanous167e2372018-05-07 11:59:10 -0700526 t->finished = 1;
527 sd_bus_slot_unref(t->slot);
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500528
Ed Tanous167e2372018-05-07 11:59:10 -0700529 if (t->callback)
530 t->callback(r, t->userdata);
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500531}
532
Brad Bishop75057c82021-08-03 15:22:02 -0400533_public_ int mapper_subtree_async(sd_bus* conn, sd_event* loop, char* namespace,
534 char* interface, void (*callback)(int, void*),
535 void* userdata, mapper_async_subtree** t,
536 int op)
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500537{
Ed Tanous167e2372018-05-07 11:59:10 -0700538 int r = 0;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500539 mapper_async_subtree* subtree = NULL;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500540
Ed Tanous167e2372018-05-07 11:59:10 -0700541 subtree = malloc(sizeof(*subtree));
542 if (!subtree)
543 return -ENOMEM;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500544
Ed Tanous167e2372018-05-07 11:59:10 -0700545 memset(subtree, 0, sizeof(*subtree));
546 subtree->conn = conn;
547 subtree->loop = loop;
548 subtree->namespace = namespace;
549 subtree->interface = interface;
550 subtree->callback = callback;
551 subtree->userdata = userdata;
552 subtree->op = op;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500553
Ed Tanous167e2372018-05-07 11:59:10 -0700554 if (subtree->op == MAPPER_OP_REMOVE)
555 {
556 r = sd_bus_add_match(conn, &subtree->slot, interfaces_removed_match,
557 async_subtree_match_callback, subtree);
558 if (r < 0)
559 {
560 fprintf(stderr, "Error adding match rule: %s\n", strerror(-r));
561 goto unref_slot;
562 }
563 }
564 else
565 {
566 /* Operation not supported */
567 r = -EINVAL;
568 goto free_subtree;
569 }
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500570
Ed Tanous167e2372018-05-07 11:59:10 -0700571 r = async_subtree_getpaths(subtree);
572 if (r < 0)
573 {
574 fprintf(stderr, "Error calling method: %s\n", strerror(-r));
575 goto unref_slot;
576 }
Adriana Kobylak025d7952017-05-08 13:30:45 -0500577
Ed Tanous167e2372018-05-07 11:59:10 -0700578 *t = subtree;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500579
Ed Tanous167e2372018-05-07 11:59:10 -0700580 return 0;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500581
582unref_slot:
Ed Tanous167e2372018-05-07 11:59:10 -0700583 sd_bus_slot_unref(subtree->slot);
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500584free_subtree:
Ed Tanous167e2372018-05-07 11:59:10 -0700585 free(subtree);
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500586
Ed Tanous167e2372018-05-07 11:59:10 -0700587 return r;
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500588}
589
Brad Bishop75057c82021-08-03 15:22:02 -0400590_public_ int mapper_get_object(sd_bus* conn, const char* obj,
591 sd_bus_message** reply)
Brad Bishop62ece2b2016-07-25 09:00:51 -0400592{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500593 sd_bus_message* request = NULL;
Ed Tanous167e2372018-05-07 11:59:10 -0700594 int r, retry = 0;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400595
Ed Tanous167e2372018-05-07 11:59:10 -0700596 r = sd_bus_message_new_method_call(conn, &request, MAPPER_BUSNAME,
597 MAPPER_PATH, MAPPER_INTERFACE,
598 "GetObject");
599 if (r < 0)
600 goto exit;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400601
Ed Tanous167e2372018-05-07 11:59:10 -0700602 r = sd_bus_message_append(request, "s", obj);
603 if (r < 0)
604 goto exit;
605 r = sd_bus_message_append(request, "as", 0, NULL);
606 if (r < 0)
607 goto exit;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400608
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700609 while (true)
Ed Tanous167e2372018-05-07 11:59:10 -0700610 {
William A. Kennington III24829462018-06-15 10:10:25 -0700611 r = sd_bus_call(conn, request, 0, NULL, reply);
612 if (r == -EBUSY || r == -ENOBUFS)
Ed Tanous167e2372018-05-07 11:59:10 -0700613 {
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700614 if (retry >= mapper_busy_retries)
615 break;
Brad Bishop3d468792016-09-20 15:39:38 -0400616
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700617 usleep(mapper_busy_delay_interval_usec * (1 << retry));
618 ++retry;
Ed Tanous167e2372018-05-07 11:59:10 -0700619 continue;
620 }
621 break;
622 }
Brad Bishop3d468792016-09-20 15:39:38 -0400623
Ed Tanous167e2372018-05-07 11:59:10 -0700624 if (r < 0)
625 goto exit;
Brad Bishop3d468792016-09-20 15:39:38 -0400626
627exit:
Ed Tanous167e2372018-05-07 11:59:10 -0700628 sd_bus_message_unref(request);
Brad Bishop3d468792016-09-20 15:39:38 -0400629
Ed Tanous167e2372018-05-07 11:59:10 -0700630 return r;
Brad Bishop3d468792016-09-20 15:39:38 -0400631}
632
Brad Bishop75057c82021-08-03 15:22:02 -0400633_public_ int mapper_get_service(sd_bus* conn, const char* obj, char** service)
Brad Bishop3d468792016-09-20 15:39:38 -0400634{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500635 sd_bus_message* reply = NULL;
636 const char* tmp;
Ed Tanous167e2372018-05-07 11:59:10 -0700637 int r;
Brad Bishop3d468792016-09-20 15:39:38 -0400638
Ed Tanous167e2372018-05-07 11:59:10 -0700639 r = mapper_get_object(conn, obj, &reply);
640 if (r < 0)
641 goto exit;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400642
Ed Tanous167e2372018-05-07 11:59:10 -0700643 r = sd_bus_message_enter_container(reply, 0, NULL);
644 if (r < 0)
645 goto exit;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400646
Ed Tanous167e2372018-05-07 11:59:10 -0700647 r = sd_bus_message_enter_container(reply, 0, NULL);
648 if (r < 0)
649 goto exit;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400650
Ed Tanous167e2372018-05-07 11:59:10 -0700651 r = sd_bus_message_read(reply, "s", &tmp);
652 if (r < 0)
653 goto exit;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400654
Ed Tanous167e2372018-05-07 11:59:10 -0700655 *service = strdup(tmp);
Brad Bishop62ece2b2016-07-25 09:00:51 -0400656
657exit:
Ed Tanous167e2372018-05-07 11:59:10 -0700658 sd_bus_message_unref(reply);
Brad Bishop62ece2b2016-07-25 09:00:51 -0400659
Ed Tanous167e2372018-05-07 11:59:10 -0700660 return r;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400661}