blob: 1d00a322f3a1a41c4973dcdfea83aa941f7ab52a [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")))
Brad Bishop2d41d6a2021-08-03 08:14:45 -040033#define _unused_ __attribute__((unused))
Brad Bishop75057c82021-08-03 15:22:02 -040034
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050035static const char* async_wait_introspection_match =
Ed Tanous167e2372018-05-07 11:59:10 -070036 "type='signal',"
37 "sender='xyz.openbmc_project.ObjectMapper',"
38 "interface='xyz.openbmc_project.ObjectMapper.Private',"
39 "member='IntrospectionComplete'";
Brad Bishop2afe7182016-08-13 14:08:17 -040040
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050041static const char* async_wait_interfaces_added_match =
Ed Tanous167e2372018-05-07 11:59:10 -070042 "type='signal',"
43 "interface='org.freedesktop.DBus.ObjectManager',"
44 "member='InterfacesAdded'";
Brad Bishop2afe7182016-08-13 14:08:17 -040045
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050046static const char* interfaces_removed_match =
Ed Tanous167e2372018-05-07 11:59:10 -070047 "type='signal',"
48 "interface='org.freedesktop.DBus.ObjectManager',"
49 "member='InterfacesRemoved'";
Adriana Kobylak78edbb62017-05-04 15:45:19 -050050
Brad Bishop3d468792016-09-20 15:39:38 -040051static const int mapper_busy_retries = 5;
52static const uint64_t mapper_busy_delay_interval_usec = 1000000;
53
Brad Bishop2afe7182016-08-13 14:08:17 -040054struct mapper_async_wait
55{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050056 char** objs;
57 void (*callback)(int, void*);
58 void* userdata;
59 sd_event* loop;
60 sd_bus* conn;
61 sd_bus_slot* introspection_slot;
62 sd_bus_slot* intf_slot;
63 int* status;
Ed Tanous167e2372018-05-07 11:59:10 -070064 int count;
65 int finished;
66 int r;
Brad Bishop2afe7182016-08-13 14:08:17 -040067};
68
69struct async_wait_callback_data
70{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050071 mapper_async_wait* wait;
72 const char* path;
73 sd_event_source* event_source;
Ed Tanous167e2372018-05-07 11:59:10 -070074 int retry;
Brad Bishop2afe7182016-08-13 14:08:17 -040075};
76
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -050077struct mapper_async_subtree
78{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050079 char* namespace;
80 char* interface;
81 void (*callback)(int, void*);
82 void* userdata;
83 sd_event* loop;
84 sd_bus* conn;
85 sd_bus_slot* slot;
86 sd_event_source* event_source;
Ed Tanous167e2372018-05-07 11:59:10 -070087 int finished;
88 int op;
89 int retry;
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -050090};
91
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050092static int async_wait_match_introspection_complete(sd_bus_message*, void*,
93 sd_bus_error*);
94static int async_wait_check_done(mapper_async_wait*);
95static void async_wait_done(int r, mapper_async_wait*);
96static int async_wait_get_objects(mapper_async_wait*);
97static int async_wait_getobject_callback(sd_bus_message*, void*, sd_bus_error*);
Brad Bishop2afe7182016-08-13 14:08:17 -040098
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050099static int async_subtree_match_callback(sd_bus_message*, void*, sd_bus_error*);
100static void async_subtree_done(int r, mapper_async_subtree*);
101static int async_subtree_getpaths(mapper_async_subtree*);
102static int async_subtree_getpaths_callback(sd_bus_message*, void*,
103 sd_bus_error*);
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500104
Brad Bishopa669a502021-08-03 16:01:43 -0400105int sarraylen(char* array[])
Brad Bishop2afe7182016-08-13 14:08:17 -0400106{
Ed Tanous167e2372018-05-07 11:59:10 -0700107 int count = 0;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500108 char** p = array;
Brad Bishop2afe7182016-08-13 14:08:17 -0400109
Ed Tanous167e2372018-05-07 11:59:10 -0700110 while (*p != NULL)
111 {
112 ++count;
113 ++p;
114 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400115
Ed Tanous167e2372018-05-07 11:59:10 -0700116 return count;
Brad Bishop2afe7182016-08-13 14:08:17 -0400117}
118
Brad Bishopa669a502021-08-03 16:01:43 -0400119void sarrayfree(char* array[])
Brad Bishop2afe7182016-08-13 14:08:17 -0400120{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500121 char** p = array;
Ed Tanous167e2372018-05-07 11:59:10 -0700122 while (*p != NULL)
123 {
124 free(*p);
125 ++p;
126 }
127 free(array);
Brad Bishop2afe7182016-08-13 14:08:17 -0400128}
129
Brad Bishopa669a502021-08-03 16:01:43 -0400130char** sarraydup(char* array[])
Brad Bishop2afe7182016-08-13 14:08:17 -0400131{
Ed Tanous167e2372018-05-07 11:59:10 -0700132 int count = sarraylen(array);
133 int i;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500134 char** ret = NULL;
Brad Bishop2afe7182016-08-13 14:08:17 -0400135
Brad Bishopa669a502021-08-03 16:01:43 -0400136 ret = calloc(count + 1, sizeof(*ret));
Ed Tanous167e2372018-05-07 11:59:10 -0700137 if (!ret)
138 return NULL;
Brad Bishop2afe7182016-08-13 14:08:17 -0400139
Ed Tanous167e2372018-05-07 11:59:10 -0700140 for (i = 0; i < count; ++i)
141 {
142 ret[i] = strdup(array[i]);
143 if (!ret[i])
144 goto error;
145 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400146
Ed Tanous167e2372018-05-07 11:59:10 -0700147 return ret;
Brad Bishop2afe7182016-08-13 14:08:17 -0400148
149error:
Ed Tanous167e2372018-05-07 11:59:10 -0700150 sarrayfree(ret);
151 return NULL;
Brad Bishop2afe7182016-08-13 14:08:17 -0400152}
153
Brad Bishop2d41d6a2021-08-03 08:14:45 -0400154static int async_wait_timeout_callback(_unused_ sd_event_source* s,
155 _unused_ uint64_t usec, void* userdata)
Brad Bishop3d468792016-09-20 15:39:38 -0400156{
Ed Tanous167e2372018-05-07 11:59:10 -0700157 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500158 struct async_wait_callback_data* data = userdata;
159 mapper_async_wait* wait = data->wait;
Brad Bishop3d468792016-09-20 15:39:38 -0400160
Ed Tanous167e2372018-05-07 11:59:10 -0700161 sd_event_source_unref(data->event_source);
162 r = sd_bus_call_method_async(wait->conn, NULL, MAPPER_BUSNAME, MAPPER_PATH,
163 MAPPER_INTERFACE, "GetObject",
164 async_wait_getobject_callback, data, "sas",
165 data->path, 0, NULL);
166 if (r < 0)
167 {
168 async_wait_done(r, wait);
169 free(data);
170 }
Brad Bishop3d468792016-09-20 15:39:38 -0400171
Ed Tanous167e2372018-05-07 11:59:10 -0700172 return 0;
Brad Bishop3d468792016-09-20 15:39:38 -0400173}
174
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500175static int async_wait_getobject_callback(sd_bus_message* m, void* userdata,
Brad Bishop2d41d6a2021-08-03 08:14:45 -0400176 _unused_ sd_bus_error* e)
Brad Bishop2afe7182016-08-13 14:08:17 -0400177{
Ed Tanous167e2372018-05-07 11:59:10 -0700178 int i, r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500179 struct async_wait_callback_data* data = userdata;
180 mapper_async_wait* wait = data->wait;
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700181 uint64_t next_retry;
Brad Bishop2afe7182016-08-13 14:08:17 -0400182
Ed Tanous167e2372018-05-07 11:59:10 -0700183 if (wait->finished)
184 goto exit;
Brad Bishop3d468792016-09-20 15:39:38 -0400185
Patrick Williamse82b0582020-11-16 16:25:20 -0600186 if (sd_bus_message_is_method_error(
187 m, "xyz.openbmc_project.Common.Error.ResourceNotFound"))
Ed Tanous167e2372018-05-07 11:59:10 -0700188 goto exit;
Brad Bishop8ccdaed2016-09-20 15:54:32 -0400189
Patrick Williamse82b0582020-11-16 16:25:20 -0600190 r = sd_bus_message_get_errno(m);
191
William A. Kennington III24829462018-06-15 10:10:25 -0700192 if ((r == EBUSY || r == ENOBUFS) && data->retry < mapper_busy_retries)
Ed Tanous167e2372018-05-07 11:59:10 -0700193 {
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700194 r = sd_event_now(wait->loop, CLOCK_MONOTONIC, &next_retry);
Ed Tanous167e2372018-05-07 11:59:10 -0700195 if (r < 0)
196 {
197 async_wait_done(r, wait);
198 goto exit;
199 }
Brad Bishop3d468792016-09-20 15:39:38 -0400200
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700201 next_retry += mapper_busy_delay_interval_usec * (1 << data->retry);
Ed Tanous167e2372018-05-07 11:59:10 -0700202 r = sd_event_add_time(wait->loop, &data->event_source, CLOCK_MONOTONIC,
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700203 next_retry, 0, async_wait_timeout_callback, data);
204 ++data->retry;
Ed Tanous167e2372018-05-07 11:59:10 -0700205 if (r < 0)
206 {
207 async_wait_done(r, wait);
208 goto exit;
209 }
Brad Bishop3d468792016-09-20 15:39:38 -0400210
Ed Tanous167e2372018-05-07 11:59:10 -0700211 return 0;
212 }
Brad Bishop3d468792016-09-20 15:39:38 -0400213
Ed Tanous167e2372018-05-07 11:59:10 -0700214 if (r)
215 {
216 async_wait_done(-r, wait);
217 goto exit;
218 }
Brad Bishop3d468792016-09-20 15:39:38 -0400219
Ed Tanous167e2372018-05-07 11:59:10 -0700220 for (i = 0; i < wait->count; ++i)
221 {
222 if (!strcmp(data->path, wait->objs[i]))
223 {
224 wait->status[i] = 1;
225 }
226 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400227
Ed Tanous167e2372018-05-07 11:59:10 -0700228 if (async_wait_check_done(wait))
229 async_wait_done(0, wait);
Brad Bishop2afe7182016-08-13 14:08:17 -0400230
Brad Bishop3d468792016-09-20 15:39:38 -0400231exit:
Ed Tanous167e2372018-05-07 11:59:10 -0700232 free(data);
233 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400234}
235
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500236static int async_wait_get_objects(mapper_async_wait* wait)
Brad Bishop2afe7182016-08-13 14:08:17 -0400237{
Ed Tanous167e2372018-05-07 11:59:10 -0700238 int i, r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500239 struct async_wait_callback_data* data = NULL;
Brad Bishop2afe7182016-08-13 14:08:17 -0400240
Ed Tanous167e2372018-05-07 11:59:10 -0700241 for (i = 0; i < wait->count; ++i)
242 {
243 if (wait->status[i])
244 continue;
245 data = malloc(sizeof(*data));
246 data->wait = wait;
247 data->path = wait->objs[i];
248 data->retry = 0;
249 data->event_source = NULL;
250 r = sd_bus_call_method_async(wait->conn, NULL, MAPPER_BUSNAME,
251 MAPPER_PATH, MAPPER_INTERFACE, "GetObject",
252 async_wait_getobject_callback, data, "sas",
253 wait->objs[i], 0, NULL);
254 if (r < 0)
255 {
256 free(data);
257 fprintf(stderr, "Error invoking method: %s\n", strerror(-r));
258 return r;
259 }
260 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400261
Ed Tanous167e2372018-05-07 11:59:10 -0700262 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400263}
264
Brad Bishop2d41d6a2021-08-03 08:14:45 -0400265static int async_wait_match_introspection_complete(_unused_ sd_bus_message* m,
266 void* w,
267 _unused_ sd_bus_error* e)
Brad Bishop2afe7182016-08-13 14:08:17 -0400268{
Ed Tanous167e2372018-05-07 11:59:10 -0700269 int r;
Brad Bishop2afe7182016-08-13 14:08:17 -0400270
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500271 mapper_async_wait* wait = w;
Ed Tanous167e2372018-05-07 11:59:10 -0700272 if (wait->finished)
273 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400274
Ed Tanous167e2372018-05-07 11:59:10 -0700275 r = async_wait_get_objects(wait);
276 if (r < 0)
277 async_wait_done(r, wait);
Brad Bishop2afe7182016-08-13 14:08:17 -0400278
Ed Tanous167e2372018-05-07 11:59:10 -0700279 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400280}
281
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500282static void async_wait_done(int r, mapper_async_wait* w)
Brad Bishop2afe7182016-08-13 14:08:17 -0400283{
Ed Tanous167e2372018-05-07 11:59:10 -0700284 if (w->finished)
285 return;
Brad Bishop2afe7182016-08-13 14:08:17 -0400286
Ed Tanous167e2372018-05-07 11:59:10 -0700287 w->finished = 1;
288 sd_bus_slot_unref(w->introspection_slot);
289 sd_bus_slot_unref(w->intf_slot);
Brad Bishop2afe7182016-08-13 14:08:17 -0400290
Ed Tanous167e2372018-05-07 11:59:10 -0700291 if (w->callback)
292 w->callback(r, w->userdata);
Brad Bishop2afe7182016-08-13 14:08:17 -0400293}
294
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500295static int async_wait_check_done(mapper_async_wait* w)
Brad Bishop2afe7182016-08-13 14:08:17 -0400296{
Ed Tanous167e2372018-05-07 11:59:10 -0700297 int i;
Brad Bishop2afe7182016-08-13 14:08:17 -0400298
Ed Tanous167e2372018-05-07 11:59:10 -0700299 if (w->finished)
300 return 1;
Brad Bishop2afe7182016-08-13 14:08:17 -0400301
Ed Tanous167e2372018-05-07 11:59:10 -0700302 for (i = 0; i < w->count; ++i)
303 if (!w->status[i])
304 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400305
Ed Tanous167e2372018-05-07 11:59:10 -0700306 return 1;
Brad Bishop2afe7182016-08-13 14:08:17 -0400307}
308
Brad Bishop75057c82021-08-03 15:22:02 -0400309_public_ void mapper_wait_async_free(mapper_async_wait* w)
Brad Bishop2afe7182016-08-13 14:08:17 -0400310{
Ed Tanous167e2372018-05-07 11:59:10 -0700311 free(w->status);
312 sarrayfree(w->objs);
313 free(w);
Brad Bishop2afe7182016-08-13 14:08:17 -0400314}
315
Brad Bishop75057c82021-08-03 15:22:02 -0400316_public_ int mapper_wait_async(sd_bus* conn, sd_event* loop, char* objs[],
317 void (*callback)(int, void*), void* userdata,
318 mapper_async_wait** w)
Brad Bishop2afe7182016-08-13 14:08:17 -0400319{
Ed Tanous167e2372018-05-07 11:59:10 -0700320 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500321 mapper_async_wait* wait = NULL;
Brad Bishop2afe7182016-08-13 14:08:17 -0400322
Ed Tanous167e2372018-05-07 11:59:10 -0700323 wait = malloc(sizeof(*wait));
324 if (!wait)
325 return -ENOMEM;
Brad Bishop2afe7182016-08-13 14:08:17 -0400326
Ed Tanous167e2372018-05-07 11:59:10 -0700327 memset(wait, 0, sizeof(*wait));
328 wait->conn = conn;
329 wait->loop = loop;
330 wait->callback = callback;
331 wait->userdata = userdata;
332 wait->count = sarraylen(objs);
333 if (!wait->count)
334 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400335
Ed Tanous167e2372018-05-07 11:59:10 -0700336 wait->objs = sarraydup(objs);
337 if (!wait->objs)
338 {
339 r = -ENOMEM;
340 goto free_wait;
341 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400342
Ed Tanous167e2372018-05-07 11:59:10 -0700343 wait->status = malloc(sizeof(*wait->status) * wait->count);
344 if (!wait->status)
345 {
346 r = -ENOMEM;
347 goto free_objs;
348 }
349 memset(wait->status, 0, sizeof(*wait->status) * wait->count);
Brad Bishop2afe7182016-08-13 14:08:17 -0400350
Ed Tanous167e2372018-05-07 11:59:10 -0700351 r = sd_bus_add_match(conn, &wait->introspection_slot,
352 async_wait_introspection_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 free_status;
358 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400359
Ed Tanous167e2372018-05-07 11:59:10 -0700360 r = sd_bus_add_match(conn, &wait->intf_slot,
361 async_wait_interfaces_added_match,
362 async_wait_match_introspection_complete, wait);
363 if (r < 0)
364 {
365 fprintf(stderr, "Error adding match rule: %s\n", strerror(-r));
366 goto unref_name_slot;
367 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400368
Ed Tanous167e2372018-05-07 11:59:10 -0700369 r = async_wait_get_objects(wait);
370 if (r < 0)
371 {
372 fprintf(stderr, "Error calling method: %s\n", strerror(-r));
373 goto unref_intf_slot;
374 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400375
Ed Tanous167e2372018-05-07 11:59:10 -0700376 *w = wait;
Brad Bishop2afe7182016-08-13 14:08:17 -0400377
Ed Tanous167e2372018-05-07 11:59:10 -0700378 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400379
380unref_intf_slot:
Ed Tanous167e2372018-05-07 11:59:10 -0700381 sd_bus_slot_unref(wait->intf_slot);
Brad Bishop2afe7182016-08-13 14:08:17 -0400382unref_name_slot:
Ed Tanous167e2372018-05-07 11:59:10 -0700383 sd_bus_slot_unref(wait->introspection_slot);
Brad Bishop2afe7182016-08-13 14:08:17 -0400384free_status:
Ed Tanous167e2372018-05-07 11:59:10 -0700385 free(wait->status);
Brad Bishop2afe7182016-08-13 14:08:17 -0400386free_objs:
Ed Tanous167e2372018-05-07 11:59:10 -0700387 sarrayfree(wait->objs);
Brad Bishop2afe7182016-08-13 14:08:17 -0400388free_wait:
Ed Tanous167e2372018-05-07 11:59:10 -0700389 free(wait);
Brad Bishop2afe7182016-08-13 14:08:17 -0400390
Ed Tanous167e2372018-05-07 11:59:10 -0700391 return r;
Brad Bishop2afe7182016-08-13 14:08:17 -0400392}
393
Brad Bishop2d41d6a2021-08-03 08:14:45 -0400394static int async_subtree_timeout_callback(_unused_ sd_event_source* s,
395 _unused_ uint64_t usec,
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500396 void* userdata)
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500397{
Ed Tanous167e2372018-05-07 11:59:10 -0700398 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500399 struct mapper_async_subtree* subtree = userdata;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500400
Ed Tanous167e2372018-05-07 11:59:10 -0700401 sd_event_source_unref(subtree->event_source);
402 r = sd_bus_call_method_async(
403 subtree->conn, NULL, MAPPER_BUSNAME, MAPPER_PATH, MAPPER_INTERFACE,
404 "GetSubTreePaths", async_subtree_getpaths_callback, subtree, "sias",
405 subtree->namespace, 0, 1, subtree->interface);
406 if (r < 0)
407 async_subtree_done(r, subtree);
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500408
Ed Tanous167e2372018-05-07 11:59:10 -0700409 return 0;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500410}
411
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500412static int async_subtree_getpaths_callback(sd_bus_message* m, void* userdata,
Brad Bishop2d41d6a2021-08-03 08:14:45 -0400413 _unused_ sd_bus_error* e)
Adriana Kobylak025d7952017-05-08 13:30:45 -0500414{
Ed Tanous167e2372018-05-07 11:59:10 -0700415 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500416 struct mapper_async_subtree* subtree = userdata;
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700417 uint64_t next_retry;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500418
Ed Tanous167e2372018-05-07 11:59:10 -0700419 if (subtree->finished)
420 goto exit;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500421
Ed Tanous167e2372018-05-07 11:59:10 -0700422 r = sd_bus_message_get_errno(m);
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500423
Patrick Williamse82b0582020-11-16 16:25:20 -0600424 if (sd_bus_message_is_method_error(
425 m, "xyz.openbmc_project.Common.Error.ResourceNotFound"))
Ed Tanous167e2372018-05-07 11:59:10 -0700426 {
427 if (subtree->op == MAPPER_OP_REMOVE)
428 r = 0;
429 else
430 goto exit;
431 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500432
William A. Kennington III24829462018-06-15 10:10:25 -0700433 if ((r == EBUSY || r == ENOBUFS) && subtree->retry < mapper_busy_retries)
Ed Tanous167e2372018-05-07 11:59:10 -0700434 {
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700435 r = sd_event_now(subtree->loop, CLOCK_MONOTONIC, &next_retry);
Ed Tanous167e2372018-05-07 11:59:10 -0700436 if (r < 0)
437 {
438 async_subtree_done(r, subtree);
439 goto exit;
440 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500441
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700442 next_retry += mapper_busy_delay_interval_usec * (1 << subtree->retry);
Ed Tanous167e2372018-05-07 11:59:10 -0700443 r = sd_event_add_time(subtree->loop, &subtree->event_source,
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700444 CLOCK_MONOTONIC, next_retry, 0,
Ed Tanous167e2372018-05-07 11:59:10 -0700445 async_subtree_timeout_callback, subtree);
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700446 ++subtree->retry;
Ed Tanous167e2372018-05-07 11:59:10 -0700447 if (r < 0)
448 {
449 async_subtree_done(r, subtree);
450 goto exit;
451 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500452
Ed Tanous167e2372018-05-07 11:59:10 -0700453 return 0;
454 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500455
Ed Tanous167e2372018-05-07 11:59:10 -0700456 if (r)
457 {
458 async_subtree_done(-r, subtree);
459 goto exit;
460 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500461
Ed Tanous167e2372018-05-07 11:59:10 -0700462 if (subtree->op == MAPPER_OP_REMOVE)
463 {
William A. Kennington III20cbbfb2018-06-15 10:10:13 -0700464 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "s");
465 if (r < 0)
466 {
467 async_subtree_done(r, subtree);
468 goto exit;
469 }
470
471 r = sd_bus_message_at_end(m, false);
472 if (r < 0)
473 {
474 async_subtree_done(r, subtree);
475 goto exit;
476 }
477
Ed Tanous167e2372018-05-07 11:59:10 -0700478 /* For remove, operation is complete when the interface is not present
William A. Kennington III20cbbfb2018-06-15 10:10:13 -0700479 * we know it is empty if the returned array is empty
Ed Tanous167e2372018-05-07 11:59:10 -0700480 */
William A. Kennington III20cbbfb2018-06-15 10:10:13 -0700481 if (r)
Ed Tanous167e2372018-05-07 11:59:10 -0700482 async_subtree_done(0, subtree);
483 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500484
485exit:
Ed Tanous167e2372018-05-07 11:59:10 -0700486 return 0;
Adriana Kobylak025d7952017-05-08 13:30:45 -0500487}
488
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500489static int async_subtree_getpaths(mapper_async_subtree* subtree)
Adriana Kobylak025d7952017-05-08 13:30:45 -0500490{
Ed Tanous167e2372018-05-07 11:59:10 -0700491 int r = 0;
Adriana Kobylak025d7952017-05-08 13:30:45 -0500492
Ed Tanous167e2372018-05-07 11:59:10 -0700493 subtree->retry = 0;
494 subtree->event_source = NULL;
495 r = sd_bus_call_method_async(
496 subtree->conn, NULL, MAPPER_BUSNAME, MAPPER_PATH, MAPPER_INTERFACE,
497 "GetSubTreePaths", async_subtree_getpaths_callback, subtree, "sias",
498 subtree->namespace, 0, 1, subtree->interface);
499 if (r < 0)
500 {
501 fprintf(stderr, "Error invoking method: %s\n", strerror(-r));
502 return r;
503 }
Adriana Kobylak025d7952017-05-08 13:30:45 -0500504
Ed Tanous167e2372018-05-07 11:59:10 -0700505 return 0;
Adriana Kobylak025d7952017-05-08 13:30:45 -0500506}
507
Brad Bishop2d41d6a2021-08-03 08:14:45 -0400508static int async_subtree_match_callback(_unused_ sd_bus_message* m, void* t,
509 _unused_ sd_bus_error* e)
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500510{
Ed Tanous167e2372018-05-07 11:59:10 -0700511 int r;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500512
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500513 mapper_async_subtree* subtree = t;
Ed Tanous167e2372018-05-07 11:59:10 -0700514 if (subtree->finished)
515 return 0;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500516
Ed Tanous167e2372018-05-07 11:59:10 -0700517 r = async_subtree_getpaths(subtree);
518 if (r < 0)
519 async_subtree_done(r, subtree);
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500520
Ed Tanous167e2372018-05-07 11:59:10 -0700521 return 0;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500522}
523
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500524static void async_subtree_done(int r, mapper_async_subtree* t)
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500525{
Ed Tanous167e2372018-05-07 11:59:10 -0700526 if (t->finished)
527 return;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500528
Ed Tanous167e2372018-05-07 11:59:10 -0700529 t->finished = 1;
530 sd_bus_slot_unref(t->slot);
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500531
Ed Tanous167e2372018-05-07 11:59:10 -0700532 if (t->callback)
533 t->callback(r, t->userdata);
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500534}
535
Brad Bishop75057c82021-08-03 15:22:02 -0400536_public_ int mapper_subtree_async(sd_bus* conn, sd_event* loop, char* namespace,
537 char* interface, void (*callback)(int, void*),
538 void* userdata, mapper_async_subtree** t,
539 int op)
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500540{
Ed Tanous167e2372018-05-07 11:59:10 -0700541 int r = 0;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500542 mapper_async_subtree* subtree = NULL;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500543
Ed Tanous167e2372018-05-07 11:59:10 -0700544 subtree = malloc(sizeof(*subtree));
545 if (!subtree)
546 return -ENOMEM;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500547
Ed Tanous167e2372018-05-07 11:59:10 -0700548 memset(subtree, 0, sizeof(*subtree));
549 subtree->conn = conn;
550 subtree->loop = loop;
551 subtree->namespace = namespace;
552 subtree->interface = interface;
553 subtree->callback = callback;
554 subtree->userdata = userdata;
555 subtree->op = op;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500556
Ed Tanous167e2372018-05-07 11:59:10 -0700557 if (subtree->op == MAPPER_OP_REMOVE)
558 {
559 r = sd_bus_add_match(conn, &subtree->slot, interfaces_removed_match,
560 async_subtree_match_callback, subtree);
561 if (r < 0)
562 {
563 fprintf(stderr, "Error adding match rule: %s\n", strerror(-r));
564 goto unref_slot;
565 }
566 }
567 else
568 {
569 /* Operation not supported */
570 r = -EINVAL;
571 goto free_subtree;
572 }
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500573
Ed Tanous167e2372018-05-07 11:59:10 -0700574 r = async_subtree_getpaths(subtree);
575 if (r < 0)
576 {
577 fprintf(stderr, "Error calling method: %s\n", strerror(-r));
578 goto unref_slot;
579 }
Adriana Kobylak025d7952017-05-08 13:30:45 -0500580
Ed Tanous167e2372018-05-07 11:59:10 -0700581 *t = subtree;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500582
Ed Tanous167e2372018-05-07 11:59:10 -0700583 return 0;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500584
585unref_slot:
Ed Tanous167e2372018-05-07 11:59:10 -0700586 sd_bus_slot_unref(subtree->slot);
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500587free_subtree:
Ed Tanous167e2372018-05-07 11:59:10 -0700588 free(subtree);
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500589
Ed Tanous167e2372018-05-07 11:59:10 -0700590 return r;
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500591}
592
Brad Bishop75057c82021-08-03 15:22:02 -0400593_public_ int mapper_get_object(sd_bus* conn, const char* obj,
594 sd_bus_message** reply)
Brad Bishop62ece2b2016-07-25 09:00:51 -0400595{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500596 sd_bus_message* request = NULL;
Ed Tanous167e2372018-05-07 11:59:10 -0700597 int r, retry = 0;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400598
Ed Tanous167e2372018-05-07 11:59:10 -0700599 r = sd_bus_message_new_method_call(conn, &request, MAPPER_BUSNAME,
600 MAPPER_PATH, MAPPER_INTERFACE,
601 "GetObject");
602 if (r < 0)
603 goto exit;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400604
Ed Tanous167e2372018-05-07 11:59:10 -0700605 r = sd_bus_message_append(request, "s", obj);
606 if (r < 0)
607 goto exit;
608 r = sd_bus_message_append(request, "as", 0, NULL);
609 if (r < 0)
610 goto exit;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400611
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700612 while (true)
Ed Tanous167e2372018-05-07 11:59:10 -0700613 {
William A. Kennington III24829462018-06-15 10:10:25 -0700614 r = sd_bus_call(conn, request, 0, NULL, reply);
615 if (r == -EBUSY || r == -ENOBUFS)
Ed Tanous167e2372018-05-07 11:59:10 -0700616 {
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700617 if (retry >= mapper_busy_retries)
618 break;
Brad Bishop3d468792016-09-20 15:39:38 -0400619
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700620 usleep(mapper_busy_delay_interval_usec * (1 << retry));
621 ++retry;
Ed Tanous167e2372018-05-07 11:59:10 -0700622 continue;
623 }
624 break;
625 }
Brad Bishop3d468792016-09-20 15:39:38 -0400626
Ed Tanous167e2372018-05-07 11:59:10 -0700627 if (r < 0)
628 goto exit;
Brad Bishop3d468792016-09-20 15:39:38 -0400629
630exit:
Ed Tanous167e2372018-05-07 11:59:10 -0700631 sd_bus_message_unref(request);
Brad Bishop3d468792016-09-20 15:39:38 -0400632
Ed Tanous167e2372018-05-07 11:59:10 -0700633 return r;
Brad Bishop3d468792016-09-20 15:39:38 -0400634}
635
Brad Bishop75057c82021-08-03 15:22:02 -0400636_public_ int mapper_get_service(sd_bus* conn, const char* obj, char** service)
Brad Bishop3d468792016-09-20 15:39:38 -0400637{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500638 sd_bus_message* reply = NULL;
639 const char* tmp;
Ed Tanous167e2372018-05-07 11:59:10 -0700640 int r;
Brad Bishop3d468792016-09-20 15:39:38 -0400641
Ed Tanous167e2372018-05-07 11:59:10 -0700642 r = mapper_get_object(conn, obj, &reply);
643 if (r < 0)
644 goto exit;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400645
Ed Tanous167e2372018-05-07 11:59:10 -0700646 r = sd_bus_message_enter_container(reply, 0, NULL);
647 if (r < 0)
648 goto exit;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400649
Ed Tanous167e2372018-05-07 11:59:10 -0700650 r = sd_bus_message_enter_container(reply, 0, NULL);
651 if (r < 0)
652 goto exit;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400653
Ed Tanous167e2372018-05-07 11:59:10 -0700654 r = sd_bus_message_read(reply, "s", &tmp);
655 if (r < 0)
656 goto exit;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400657
Ed Tanous167e2372018-05-07 11:59:10 -0700658 *service = strdup(tmp);
Brad Bishop62ece2b2016-07-25 09:00:51 -0400659
660exit:
Ed Tanous167e2372018-05-07 11:59:10 -0700661 sd_bus_message_unref(reply);
Brad Bishop62ece2b2016-07-25 09:00:51 -0400662
Ed Tanous167e2372018-05-07 11:59:10 -0700663 return r;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400664}