blob: 3c43eb9eade075bc480b9315def7ccee6dd27588 [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>
Brad Bishopa959f122021-08-03 11:21:01 -040022#include <stddef.h>
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050023#include <stdio.h>
Brad Bishop2afe7182016-08-13 14:08:17 -040024#include <stdlib.h>
Brad Bishop62ece2b2016-07-25 09:00:51 -040025#include <string.h>
Brad Bishop3d468792016-09-20 15:39:38 -040026#include <sys/timerfd.h>
Brad Bishop62ece2b2016-07-25 09:00:51 -040027#include <systemd/sd-bus.h>
Brad Bishop3d468792016-09-20 15:39:38 -040028#include <systemd/sd-event.h>
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050029#include <unistd.h>
Brad Bishop62ece2b2016-07-25 09:00:51 -040030
Brad Bishopa669a502021-08-03 16:01:43 -040031#include "internal.h"
32
Brad Bishop75057c82021-08-03 15:22:02 -040033#define _public_ __attribute__((__visibility__("default")))
Brad Bishop2d41d6a2021-08-03 08:14:45 -040034#define _unused_ __attribute__((unused))
Brad Bishop75057c82021-08-03 15:22:02 -040035
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050036static const char* async_wait_introspection_match =
Ed Tanous167e2372018-05-07 11:59:10 -070037 "type='signal',"
38 "sender='xyz.openbmc_project.ObjectMapper',"
39 "interface='xyz.openbmc_project.ObjectMapper.Private',"
40 "member='IntrospectionComplete'";
Brad Bishop2afe7182016-08-13 14:08:17 -040041
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050042static const char* async_wait_interfaces_added_match =
Ed Tanous167e2372018-05-07 11:59:10 -070043 "type='signal',"
44 "interface='org.freedesktop.DBus.ObjectManager',"
45 "member='InterfacesAdded'";
Brad Bishop2afe7182016-08-13 14:08:17 -040046
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050047static const char* interfaces_removed_match =
Ed Tanous167e2372018-05-07 11:59:10 -070048 "type='signal',"
49 "interface='org.freedesktop.DBus.ObjectManager',"
50 "member='InterfacesRemoved'";
Adriana Kobylak78edbb62017-05-04 15:45:19 -050051
Brad Bishop3d468792016-09-20 15:39:38 -040052static const int mapper_busy_retries = 5;
53static const uint64_t mapper_busy_delay_interval_usec = 1000000;
54
Brad Bishop2afe7182016-08-13 14:08:17 -040055struct mapper_async_wait
56{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050057 char** objs;
58 void (*callback)(int, void*);
59 void* userdata;
60 sd_event* loop;
61 sd_bus* conn;
62 sd_bus_slot* introspection_slot;
63 sd_bus_slot* intf_slot;
64 int* status;
Brad Bishopa959f122021-08-03 11:21:01 -040065 size_t count;
Ed Tanous167e2372018-05-07 11:59:10 -070066 int finished;
67 int r;
Brad Bishop2afe7182016-08-13 14:08:17 -040068};
69
70struct async_wait_callback_data
71{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050072 mapper_async_wait* wait;
73 const char* path;
74 sd_event_source* event_source;
Ed Tanous167e2372018-05-07 11:59:10 -070075 int retry;
Brad Bishop2afe7182016-08-13 14:08:17 -040076};
77
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -050078struct mapper_async_subtree
79{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050080 char* namespace;
81 char* interface;
82 void (*callback)(int, void*);
83 void* userdata;
84 sd_event* loop;
85 sd_bus* conn;
86 sd_bus_slot* slot;
87 sd_event_source* event_source;
Ed Tanous167e2372018-05-07 11:59:10 -070088 int finished;
89 int op;
90 int retry;
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -050091};
92
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050093static int async_wait_match_introspection_complete(sd_bus_message*, void*,
94 sd_bus_error*);
95static int async_wait_check_done(mapper_async_wait*);
96static void async_wait_done(int r, mapper_async_wait*);
97static int async_wait_get_objects(mapper_async_wait*);
98static int async_wait_getobject_callback(sd_bus_message*, void*, sd_bus_error*);
Brad Bishop2afe7182016-08-13 14:08:17 -040099
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500100static int async_subtree_match_callback(sd_bus_message*, void*, sd_bus_error*);
101static void async_subtree_done(int r, mapper_async_subtree*);
102static int async_subtree_getpaths(mapper_async_subtree*);
103static int async_subtree_getpaths_callback(sd_bus_message*, void*,
104 sd_bus_error*);
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500105
Brad Bishopa959f122021-08-03 11:21:01 -0400106size_t sarraylen(char* array[])
Brad Bishop2afe7182016-08-13 14:08:17 -0400107{
Brad Bishopa959f122021-08-03 11:21:01 -0400108 size_t count = 0;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500109 char** p = array;
Brad Bishop2afe7182016-08-13 14:08:17 -0400110
Ed Tanous167e2372018-05-07 11:59:10 -0700111 while (*p != NULL)
112 {
113 ++count;
114 ++p;
115 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400116
Ed Tanous167e2372018-05-07 11:59:10 -0700117 return count;
Brad Bishop2afe7182016-08-13 14:08:17 -0400118}
119
Brad Bishopa669a502021-08-03 16:01:43 -0400120void sarrayfree(char* array[])
Brad Bishop2afe7182016-08-13 14:08:17 -0400121{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500122 char** p = array;
Ed Tanous167e2372018-05-07 11:59:10 -0700123 while (*p != NULL)
124 {
125 free(*p);
126 ++p;
127 }
128 free(array);
Brad Bishop2afe7182016-08-13 14:08:17 -0400129}
130
Brad Bishopa669a502021-08-03 16:01:43 -0400131char** sarraydup(char* array[])
Brad Bishop2afe7182016-08-13 14:08:17 -0400132{
Brad Bishopa959f122021-08-03 11:21:01 -0400133 size_t count = sarraylen(array);
134 size_t i;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500135 char** ret = NULL;
Brad Bishop2afe7182016-08-13 14:08:17 -0400136
Brad Bishopa669a502021-08-03 16:01:43 -0400137 ret = calloc(count + 1, sizeof(*ret));
Ed Tanous167e2372018-05-07 11:59:10 -0700138 if (!ret)
139 return NULL;
Brad Bishop2afe7182016-08-13 14:08:17 -0400140
Ed Tanous167e2372018-05-07 11:59:10 -0700141 for (i = 0; i < count; ++i)
142 {
143 ret[i] = strdup(array[i]);
144 if (!ret[i])
145 goto error;
146 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400147
Ed Tanous167e2372018-05-07 11:59:10 -0700148 return ret;
Brad Bishop2afe7182016-08-13 14:08:17 -0400149
150error:
Ed Tanous167e2372018-05-07 11:59:10 -0700151 sarrayfree(ret);
152 return NULL;
Brad Bishop2afe7182016-08-13 14:08:17 -0400153}
154
Brad Bishop2d41d6a2021-08-03 08:14:45 -0400155static int async_wait_timeout_callback(_unused_ sd_event_source* s,
156 _unused_ uint64_t usec, void* userdata)
Brad Bishop3d468792016-09-20 15:39:38 -0400157{
Ed Tanous167e2372018-05-07 11:59:10 -0700158 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500159 struct async_wait_callback_data* data = userdata;
160 mapper_async_wait* wait = data->wait;
Brad Bishop3d468792016-09-20 15:39:38 -0400161
Ed Tanous167e2372018-05-07 11:59:10 -0700162 sd_event_source_unref(data->event_source);
163 r = sd_bus_call_method_async(wait->conn, NULL, MAPPER_BUSNAME, MAPPER_PATH,
164 MAPPER_INTERFACE, "GetObject",
165 async_wait_getobject_callback, data, "sas",
166 data->path, 0, NULL);
167 if (r < 0)
168 {
169 async_wait_done(r, wait);
170 free(data);
171 }
Brad Bishop3d468792016-09-20 15:39:38 -0400172
Ed Tanous167e2372018-05-07 11:59:10 -0700173 return 0;
Brad Bishop3d468792016-09-20 15:39:38 -0400174}
175
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500176static int async_wait_getobject_callback(sd_bus_message* m, void* userdata,
Brad Bishop2d41d6a2021-08-03 08:14:45 -0400177 _unused_ sd_bus_error* e)
Brad Bishop2afe7182016-08-13 14:08:17 -0400178{
Brad Bishopa959f122021-08-03 11:21:01 -0400179 size_t i;
180 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500181 struct async_wait_callback_data* data = userdata;
182 mapper_async_wait* wait = data->wait;
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700183 uint64_t next_retry;
Brad Bishop2afe7182016-08-13 14:08:17 -0400184
Ed Tanous167e2372018-05-07 11:59:10 -0700185 if (wait->finished)
186 goto exit;
Brad Bishop3d468792016-09-20 15:39:38 -0400187
Patrick Williamse82b0582020-11-16 16:25:20 -0600188 if (sd_bus_message_is_method_error(
189 m, "xyz.openbmc_project.Common.Error.ResourceNotFound"))
Ed Tanous167e2372018-05-07 11:59:10 -0700190 goto exit;
Brad Bishop8ccdaed2016-09-20 15:54:32 -0400191
Patrick Williamse82b0582020-11-16 16:25:20 -0600192 r = sd_bus_message_get_errno(m);
193
William A. Kennington III24829462018-06-15 10:10:25 -0700194 if ((r == EBUSY || r == ENOBUFS) && data->retry < mapper_busy_retries)
Ed Tanous167e2372018-05-07 11:59:10 -0700195 {
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700196 r = sd_event_now(wait->loop, CLOCK_MONOTONIC, &next_retry);
Ed Tanous167e2372018-05-07 11:59:10 -0700197 if (r < 0)
198 {
199 async_wait_done(r, wait);
200 goto exit;
201 }
Brad Bishop3d468792016-09-20 15:39:38 -0400202
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700203 next_retry += mapper_busy_delay_interval_usec * (1 << data->retry);
Ed Tanous167e2372018-05-07 11:59:10 -0700204 r = sd_event_add_time(wait->loop, &data->event_source, CLOCK_MONOTONIC,
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700205 next_retry, 0, async_wait_timeout_callback, data);
206 ++data->retry;
Ed Tanous167e2372018-05-07 11:59:10 -0700207 if (r < 0)
208 {
209 async_wait_done(r, wait);
210 goto exit;
211 }
Brad Bishop3d468792016-09-20 15:39:38 -0400212
Ed Tanous167e2372018-05-07 11:59:10 -0700213 return 0;
214 }
Brad Bishop3d468792016-09-20 15:39:38 -0400215
Ed Tanous167e2372018-05-07 11:59:10 -0700216 if (r)
217 {
218 async_wait_done(-r, wait);
219 goto exit;
220 }
Brad Bishop3d468792016-09-20 15:39:38 -0400221
Ed Tanous167e2372018-05-07 11:59:10 -0700222 for (i = 0; i < wait->count; ++i)
223 {
224 if (!strcmp(data->path, wait->objs[i]))
225 {
226 wait->status[i] = 1;
227 }
228 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400229
Ed Tanous167e2372018-05-07 11:59:10 -0700230 if (async_wait_check_done(wait))
231 async_wait_done(0, wait);
Brad Bishop2afe7182016-08-13 14:08:17 -0400232
Brad Bishop3d468792016-09-20 15:39:38 -0400233exit:
Ed Tanous167e2372018-05-07 11:59:10 -0700234 free(data);
235 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400236}
237
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500238static int async_wait_get_objects(mapper_async_wait* wait)
Brad Bishop2afe7182016-08-13 14:08:17 -0400239{
Brad Bishopa959f122021-08-03 11:21:01 -0400240 size_t i;
241 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500242 struct async_wait_callback_data* data = NULL;
Brad Bishop2afe7182016-08-13 14:08:17 -0400243
Ed Tanous167e2372018-05-07 11:59:10 -0700244 for (i = 0; i < wait->count; ++i)
245 {
246 if (wait->status[i])
247 continue;
248 data = malloc(sizeof(*data));
249 data->wait = wait;
250 data->path = wait->objs[i];
251 data->retry = 0;
252 data->event_source = NULL;
253 r = sd_bus_call_method_async(wait->conn, NULL, MAPPER_BUSNAME,
254 MAPPER_PATH, MAPPER_INTERFACE, "GetObject",
255 async_wait_getobject_callback, data, "sas",
256 wait->objs[i], 0, NULL);
257 if (r < 0)
258 {
259 free(data);
260 fprintf(stderr, "Error invoking method: %s\n", strerror(-r));
261 return r;
262 }
263 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400264
Ed Tanous167e2372018-05-07 11:59:10 -0700265 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400266}
267
Brad Bishop2d41d6a2021-08-03 08:14:45 -0400268static int async_wait_match_introspection_complete(_unused_ sd_bus_message* m,
269 void* w,
270 _unused_ sd_bus_error* e)
Brad Bishop2afe7182016-08-13 14:08:17 -0400271{
Ed Tanous167e2372018-05-07 11:59:10 -0700272 int r;
Brad Bishop2afe7182016-08-13 14:08:17 -0400273
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500274 mapper_async_wait* wait = w;
Ed Tanous167e2372018-05-07 11:59:10 -0700275 if (wait->finished)
276 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400277
Ed Tanous167e2372018-05-07 11:59:10 -0700278 r = async_wait_get_objects(wait);
279 if (r < 0)
280 async_wait_done(r, wait);
Brad Bishop2afe7182016-08-13 14:08:17 -0400281
Ed Tanous167e2372018-05-07 11:59:10 -0700282 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400283}
284
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500285static void async_wait_done(int r, mapper_async_wait* w)
Brad Bishop2afe7182016-08-13 14:08:17 -0400286{
Ed Tanous167e2372018-05-07 11:59:10 -0700287 if (w->finished)
288 return;
Brad Bishop2afe7182016-08-13 14:08:17 -0400289
Ed Tanous167e2372018-05-07 11:59:10 -0700290 w->finished = 1;
291 sd_bus_slot_unref(w->introspection_slot);
292 sd_bus_slot_unref(w->intf_slot);
Brad Bishop2afe7182016-08-13 14:08:17 -0400293
Ed Tanous167e2372018-05-07 11:59:10 -0700294 if (w->callback)
295 w->callback(r, w->userdata);
Brad Bishop2afe7182016-08-13 14:08:17 -0400296}
297
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500298static int async_wait_check_done(mapper_async_wait* w)
Brad Bishop2afe7182016-08-13 14:08:17 -0400299{
Brad Bishopa959f122021-08-03 11:21:01 -0400300 size_t i;
Brad Bishop2afe7182016-08-13 14:08:17 -0400301
Ed Tanous167e2372018-05-07 11:59:10 -0700302 if (w->finished)
303 return 1;
Brad Bishop2afe7182016-08-13 14:08:17 -0400304
Ed Tanous167e2372018-05-07 11:59:10 -0700305 for (i = 0; i < w->count; ++i)
306 if (!w->status[i])
307 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400308
Ed Tanous167e2372018-05-07 11:59:10 -0700309 return 1;
Brad Bishop2afe7182016-08-13 14:08:17 -0400310}
311
Brad Bishop75057c82021-08-03 15:22:02 -0400312_public_ void mapper_wait_async_free(mapper_async_wait* w)
Brad Bishop2afe7182016-08-13 14:08:17 -0400313{
Ed Tanous167e2372018-05-07 11:59:10 -0700314 free(w->status);
315 sarrayfree(w->objs);
316 free(w);
Brad Bishop2afe7182016-08-13 14:08:17 -0400317}
318
Brad Bishop75057c82021-08-03 15:22:02 -0400319_public_ int mapper_wait_async(sd_bus* conn, sd_event* loop, char* objs[],
320 void (*callback)(int, void*), void* userdata,
321 mapper_async_wait** w)
Brad Bishop2afe7182016-08-13 14:08:17 -0400322{
Ed Tanous167e2372018-05-07 11:59:10 -0700323 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500324 mapper_async_wait* wait = NULL;
Brad Bishop2afe7182016-08-13 14:08:17 -0400325
Ed Tanous167e2372018-05-07 11:59:10 -0700326 wait = malloc(sizeof(*wait));
327 if (!wait)
328 return -ENOMEM;
Brad Bishop2afe7182016-08-13 14:08:17 -0400329
Ed Tanous167e2372018-05-07 11:59:10 -0700330 memset(wait, 0, sizeof(*wait));
331 wait->conn = conn;
332 wait->loop = loop;
333 wait->callback = callback;
334 wait->userdata = userdata;
335 wait->count = sarraylen(objs);
336 if (!wait->count)
Brad Bishop2ac32332021-08-03 14:06:52 -0400337 {
338 r = 0;
339 goto free_wait;
340 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400341
Ed Tanous167e2372018-05-07 11:59:10 -0700342 wait->objs = sarraydup(objs);
343 if (!wait->objs)
344 {
345 r = -ENOMEM;
346 goto free_wait;
347 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400348
Ed Tanous167e2372018-05-07 11:59:10 -0700349 wait->status = malloc(sizeof(*wait->status) * wait->count);
350 if (!wait->status)
351 {
352 r = -ENOMEM;
353 goto free_objs;
354 }
355 memset(wait->status, 0, sizeof(*wait->status) * wait->count);
Brad Bishop2afe7182016-08-13 14:08:17 -0400356
Ed Tanous167e2372018-05-07 11:59:10 -0700357 r = sd_bus_add_match(conn, &wait->introspection_slot,
358 async_wait_introspection_match,
359 async_wait_match_introspection_complete, wait);
360 if (r < 0)
361 {
362 fprintf(stderr, "Error adding match rule: %s\n", strerror(-r));
363 goto free_status;
364 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400365
Ed Tanous167e2372018-05-07 11:59:10 -0700366 r = sd_bus_add_match(conn, &wait->intf_slot,
367 async_wait_interfaces_added_match,
368 async_wait_match_introspection_complete, wait);
369 if (r < 0)
370 {
371 fprintf(stderr, "Error adding match rule: %s\n", strerror(-r));
372 goto unref_name_slot;
373 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400374
Ed Tanous167e2372018-05-07 11:59:10 -0700375 r = async_wait_get_objects(wait);
376 if (r < 0)
377 {
378 fprintf(stderr, "Error calling method: %s\n", strerror(-r));
379 goto unref_intf_slot;
380 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400381
Ed Tanous167e2372018-05-07 11:59:10 -0700382 *w = wait;
Brad Bishop2afe7182016-08-13 14:08:17 -0400383
Ed Tanous167e2372018-05-07 11:59:10 -0700384 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400385
386unref_intf_slot:
Ed Tanous167e2372018-05-07 11:59:10 -0700387 sd_bus_slot_unref(wait->intf_slot);
Brad Bishop2afe7182016-08-13 14:08:17 -0400388unref_name_slot:
Ed Tanous167e2372018-05-07 11:59:10 -0700389 sd_bus_slot_unref(wait->introspection_slot);
Brad Bishop2afe7182016-08-13 14:08:17 -0400390free_status:
Ed Tanous167e2372018-05-07 11:59:10 -0700391 free(wait->status);
Brad Bishop2afe7182016-08-13 14:08:17 -0400392free_objs:
Ed Tanous167e2372018-05-07 11:59:10 -0700393 sarrayfree(wait->objs);
Brad Bishop2afe7182016-08-13 14:08:17 -0400394free_wait:
Ed Tanous167e2372018-05-07 11:59:10 -0700395 free(wait);
Brad Bishop2afe7182016-08-13 14:08:17 -0400396
Ed Tanous167e2372018-05-07 11:59:10 -0700397 return r;
Brad Bishop2afe7182016-08-13 14:08:17 -0400398}
399
Brad Bishop2d41d6a2021-08-03 08:14:45 -0400400static int async_subtree_timeout_callback(_unused_ sd_event_source* s,
401 _unused_ uint64_t usec,
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500402 void* userdata)
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500403{
Ed Tanous167e2372018-05-07 11:59:10 -0700404 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500405 struct mapper_async_subtree* subtree = userdata;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500406
Ed Tanous167e2372018-05-07 11:59:10 -0700407 sd_event_source_unref(subtree->event_source);
408 r = sd_bus_call_method_async(
409 subtree->conn, NULL, MAPPER_BUSNAME, MAPPER_PATH, MAPPER_INTERFACE,
410 "GetSubTreePaths", async_subtree_getpaths_callback, subtree, "sias",
411 subtree->namespace, 0, 1, subtree->interface);
412 if (r < 0)
413 async_subtree_done(r, subtree);
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500414
Ed Tanous167e2372018-05-07 11:59:10 -0700415 return 0;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500416}
417
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500418static int async_subtree_getpaths_callback(sd_bus_message* m, void* userdata,
Brad Bishop2d41d6a2021-08-03 08:14:45 -0400419 _unused_ sd_bus_error* e)
Adriana Kobylak025d7952017-05-08 13:30:45 -0500420{
Ed Tanous167e2372018-05-07 11:59:10 -0700421 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500422 struct mapper_async_subtree* subtree = userdata;
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700423 uint64_t next_retry;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500424
Ed Tanous167e2372018-05-07 11:59:10 -0700425 if (subtree->finished)
426 goto exit;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500427
Ed Tanous167e2372018-05-07 11:59:10 -0700428 r = sd_bus_message_get_errno(m);
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500429
Patrick Williamse82b0582020-11-16 16:25:20 -0600430 if (sd_bus_message_is_method_error(
431 m, "xyz.openbmc_project.Common.Error.ResourceNotFound"))
Ed Tanous167e2372018-05-07 11:59:10 -0700432 {
433 if (subtree->op == MAPPER_OP_REMOVE)
434 r = 0;
435 else
436 goto exit;
437 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500438
William A. Kennington III24829462018-06-15 10:10:25 -0700439 if ((r == EBUSY || r == ENOBUFS) && subtree->retry < mapper_busy_retries)
Ed Tanous167e2372018-05-07 11:59:10 -0700440 {
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700441 r = sd_event_now(subtree->loop, CLOCK_MONOTONIC, &next_retry);
Ed Tanous167e2372018-05-07 11:59:10 -0700442 if (r < 0)
443 {
444 async_subtree_done(r, subtree);
445 goto exit;
446 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500447
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700448 next_retry += mapper_busy_delay_interval_usec * (1 << subtree->retry);
Ed Tanous167e2372018-05-07 11:59:10 -0700449 r = sd_event_add_time(subtree->loop, &subtree->event_source,
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700450 CLOCK_MONOTONIC, next_retry, 0,
Ed Tanous167e2372018-05-07 11:59:10 -0700451 async_subtree_timeout_callback, subtree);
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700452 ++subtree->retry;
Ed Tanous167e2372018-05-07 11:59:10 -0700453 if (r < 0)
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 return 0;
460 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500461
Ed Tanous167e2372018-05-07 11:59:10 -0700462 if (r)
463 {
464 async_subtree_done(-r, subtree);
465 goto exit;
466 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500467
Ed Tanous167e2372018-05-07 11:59:10 -0700468 if (subtree->op == MAPPER_OP_REMOVE)
469 {
William A. Kennington III20cbbfb2018-06-15 10:10:13 -0700470 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "s");
471 if (r < 0)
472 {
473 async_subtree_done(r, subtree);
474 goto exit;
475 }
476
477 r = sd_bus_message_at_end(m, false);
478 if (r < 0)
479 {
480 async_subtree_done(r, subtree);
481 goto exit;
482 }
483
Ed Tanous167e2372018-05-07 11:59:10 -0700484 /* For remove, operation is complete when the interface is not present
William A. Kennington III20cbbfb2018-06-15 10:10:13 -0700485 * we know it is empty if the returned array is empty
Ed Tanous167e2372018-05-07 11:59:10 -0700486 */
William A. Kennington III20cbbfb2018-06-15 10:10:13 -0700487 if (r)
Ed Tanous167e2372018-05-07 11:59:10 -0700488 async_subtree_done(0, subtree);
489 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500490
491exit:
Ed Tanous167e2372018-05-07 11:59:10 -0700492 return 0;
Adriana Kobylak025d7952017-05-08 13:30:45 -0500493}
494
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500495static int async_subtree_getpaths(mapper_async_subtree* subtree)
Adriana Kobylak025d7952017-05-08 13:30:45 -0500496{
Ed Tanous167e2372018-05-07 11:59:10 -0700497 int r = 0;
Adriana Kobylak025d7952017-05-08 13:30:45 -0500498
Ed Tanous167e2372018-05-07 11:59:10 -0700499 subtree->retry = 0;
500 subtree->event_source = NULL;
501 r = sd_bus_call_method_async(
502 subtree->conn, NULL, MAPPER_BUSNAME, MAPPER_PATH, MAPPER_INTERFACE,
503 "GetSubTreePaths", async_subtree_getpaths_callback, subtree, "sias",
504 subtree->namespace, 0, 1, subtree->interface);
505 if (r < 0)
506 {
507 fprintf(stderr, "Error invoking method: %s\n", strerror(-r));
508 return r;
509 }
Adriana Kobylak025d7952017-05-08 13:30:45 -0500510
Ed Tanous167e2372018-05-07 11:59:10 -0700511 return 0;
Adriana Kobylak025d7952017-05-08 13:30:45 -0500512}
513
Brad Bishop2d41d6a2021-08-03 08:14:45 -0400514static int async_subtree_match_callback(_unused_ sd_bus_message* m, void* t,
515 _unused_ sd_bus_error* e)
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500516{
Ed Tanous167e2372018-05-07 11:59:10 -0700517 int r;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500518
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500519 mapper_async_subtree* subtree = t;
Ed Tanous167e2372018-05-07 11:59:10 -0700520 if (subtree->finished)
521 return 0;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500522
Ed Tanous167e2372018-05-07 11:59:10 -0700523 r = async_subtree_getpaths(subtree);
524 if (r < 0)
525 async_subtree_done(r, subtree);
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500526
Ed Tanous167e2372018-05-07 11:59:10 -0700527 return 0;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500528}
529
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500530static void async_subtree_done(int r, mapper_async_subtree* t)
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500531{
Ed Tanous167e2372018-05-07 11:59:10 -0700532 if (t->finished)
533 return;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500534
Ed Tanous167e2372018-05-07 11:59:10 -0700535 t->finished = 1;
536 sd_bus_slot_unref(t->slot);
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500537
Ed Tanous167e2372018-05-07 11:59:10 -0700538 if (t->callback)
539 t->callback(r, t->userdata);
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500540}
541
Brad Bishop75057c82021-08-03 15:22:02 -0400542_public_ int mapper_subtree_async(sd_bus* conn, sd_event* loop, char* namespace,
543 char* interface, void (*callback)(int, void*),
544 void* userdata, mapper_async_subtree** t,
545 int op)
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500546{
Ed Tanous167e2372018-05-07 11:59:10 -0700547 int r = 0;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500548 mapper_async_subtree* subtree = NULL;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500549
Ed Tanous167e2372018-05-07 11:59:10 -0700550 subtree = malloc(sizeof(*subtree));
551 if (!subtree)
552 return -ENOMEM;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500553
Ed Tanous167e2372018-05-07 11:59:10 -0700554 memset(subtree, 0, sizeof(*subtree));
555 subtree->conn = conn;
556 subtree->loop = loop;
557 subtree->namespace = namespace;
558 subtree->interface = interface;
559 subtree->callback = callback;
560 subtree->userdata = userdata;
561 subtree->op = op;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500562
Ed Tanous167e2372018-05-07 11:59:10 -0700563 if (subtree->op == MAPPER_OP_REMOVE)
564 {
565 r = sd_bus_add_match(conn, &subtree->slot, interfaces_removed_match,
566 async_subtree_match_callback, subtree);
567 if (r < 0)
568 {
569 fprintf(stderr, "Error adding match rule: %s\n", strerror(-r));
570 goto unref_slot;
571 }
572 }
573 else
574 {
575 /* Operation not supported */
576 r = -EINVAL;
577 goto free_subtree;
578 }
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500579
Ed Tanous167e2372018-05-07 11:59:10 -0700580 r = async_subtree_getpaths(subtree);
581 if (r < 0)
582 {
583 fprintf(stderr, "Error calling method: %s\n", strerror(-r));
584 goto unref_slot;
585 }
Adriana Kobylak025d7952017-05-08 13:30:45 -0500586
Ed Tanous167e2372018-05-07 11:59:10 -0700587 *t = subtree;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500588
Ed Tanous167e2372018-05-07 11:59:10 -0700589 return 0;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500590
591unref_slot:
Ed Tanous167e2372018-05-07 11:59:10 -0700592 sd_bus_slot_unref(subtree->slot);
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500593free_subtree:
Ed Tanous167e2372018-05-07 11:59:10 -0700594 free(subtree);
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500595
Ed Tanous167e2372018-05-07 11:59:10 -0700596 return r;
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500597}
598
Brad Bishop75057c82021-08-03 15:22:02 -0400599_public_ int mapper_get_object(sd_bus* conn, const char* obj,
600 sd_bus_message** reply)
Brad Bishop62ece2b2016-07-25 09:00:51 -0400601{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500602 sd_bus_message* request = NULL;
Ed Tanous167e2372018-05-07 11:59:10 -0700603 int r, retry = 0;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400604
Ed Tanous167e2372018-05-07 11:59:10 -0700605 r = sd_bus_message_new_method_call(conn, &request, MAPPER_BUSNAME,
606 MAPPER_PATH, MAPPER_INTERFACE,
607 "GetObject");
608 if (r < 0)
609 goto exit;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400610
Ed Tanous167e2372018-05-07 11:59:10 -0700611 r = sd_bus_message_append(request, "s", obj);
612 if (r < 0)
613 goto exit;
614 r = sd_bus_message_append(request, "as", 0, NULL);
615 if (r < 0)
616 goto exit;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400617
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700618 while (true)
Ed Tanous167e2372018-05-07 11:59:10 -0700619 {
William A. Kennington III24829462018-06-15 10:10:25 -0700620 r = sd_bus_call(conn, request, 0, NULL, reply);
621 if (r == -EBUSY || r == -ENOBUFS)
Ed Tanous167e2372018-05-07 11:59:10 -0700622 {
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700623 if (retry >= mapper_busy_retries)
624 break;
Brad Bishop3d468792016-09-20 15:39:38 -0400625
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700626 usleep(mapper_busy_delay_interval_usec * (1 << retry));
627 ++retry;
Ed Tanous167e2372018-05-07 11:59:10 -0700628 continue;
629 }
630 break;
631 }
Brad Bishop3d468792016-09-20 15:39:38 -0400632
Ed Tanous167e2372018-05-07 11:59:10 -0700633 if (r < 0)
634 goto exit;
Brad Bishop3d468792016-09-20 15:39:38 -0400635
636exit:
Ed Tanous167e2372018-05-07 11:59:10 -0700637 sd_bus_message_unref(request);
Brad Bishop3d468792016-09-20 15:39:38 -0400638
Ed Tanous167e2372018-05-07 11:59:10 -0700639 return r;
Brad Bishop3d468792016-09-20 15:39:38 -0400640}
641
Brad Bishop75057c82021-08-03 15:22:02 -0400642_public_ int mapper_get_service(sd_bus* conn, const char* obj, char** service)
Brad Bishop3d468792016-09-20 15:39:38 -0400643{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500644 sd_bus_message* reply = NULL;
645 const char* tmp;
Ed Tanous167e2372018-05-07 11:59:10 -0700646 int r;
Brad Bishop3d468792016-09-20 15:39:38 -0400647
Ed Tanous167e2372018-05-07 11:59:10 -0700648 r = mapper_get_object(conn, obj, &reply);
649 if (r < 0)
650 goto exit;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400651
Ed Tanous167e2372018-05-07 11:59:10 -0700652 r = sd_bus_message_enter_container(reply, 0, NULL);
653 if (r < 0)
654 goto exit;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400655
Ed Tanous167e2372018-05-07 11:59:10 -0700656 r = sd_bus_message_enter_container(reply, 0, NULL);
657 if (r < 0)
658 goto exit;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400659
Ed Tanous167e2372018-05-07 11:59:10 -0700660 r = sd_bus_message_read(reply, "s", &tmp);
661 if (r < 0)
662 goto exit;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400663
Ed Tanous167e2372018-05-07 11:59:10 -0700664 *service = strdup(tmp);
Brad Bishop62ece2b2016-07-25 09:00:51 -0400665
666exit:
Ed Tanous167e2372018-05-07 11:59:10 -0700667 sd_bus_message_unref(reply);
Brad Bishop62ece2b2016-07-25 09:00:51 -0400668
Ed Tanous167e2372018-05-07 11:59:10 -0700669 return r;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400670}