blob: fb079403a5b41b473a5f5f4253c2d7abdd8115ea [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 Bishop75057c82021-08-03 15:22:02 -040030#define _public_ __attribute__((__visibility__("default")))
31
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050032static const char* async_wait_introspection_match =
Ed Tanous167e2372018-05-07 11:59:10 -070033 "type='signal',"
34 "sender='xyz.openbmc_project.ObjectMapper',"
35 "interface='xyz.openbmc_project.ObjectMapper.Private',"
36 "member='IntrospectionComplete'";
Brad Bishop2afe7182016-08-13 14:08:17 -040037
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050038static const char* async_wait_interfaces_added_match =
Ed Tanous167e2372018-05-07 11:59:10 -070039 "type='signal',"
40 "interface='org.freedesktop.DBus.ObjectManager',"
41 "member='InterfacesAdded'";
Brad Bishop2afe7182016-08-13 14:08:17 -040042
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050043static const char* interfaces_removed_match =
Ed Tanous167e2372018-05-07 11:59:10 -070044 "type='signal',"
45 "interface='org.freedesktop.DBus.ObjectManager',"
46 "member='InterfacesRemoved'";
Adriana Kobylak78edbb62017-05-04 15:45:19 -050047
Brad Bishop3d468792016-09-20 15:39:38 -040048static const int mapper_busy_retries = 5;
49static const uint64_t mapper_busy_delay_interval_usec = 1000000;
50
Brad Bishop2afe7182016-08-13 14:08:17 -040051struct mapper_async_wait
52{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050053 char** objs;
54 void (*callback)(int, void*);
55 void* userdata;
56 sd_event* loop;
57 sd_bus* conn;
58 sd_bus_slot* introspection_slot;
59 sd_bus_slot* intf_slot;
60 int* status;
Ed Tanous167e2372018-05-07 11:59:10 -070061 int count;
62 int finished;
63 int r;
Brad Bishop2afe7182016-08-13 14:08:17 -040064};
65
66struct async_wait_callback_data
67{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050068 mapper_async_wait* wait;
69 const char* path;
70 sd_event_source* event_source;
Ed Tanous167e2372018-05-07 11:59:10 -070071 int retry;
Brad Bishop2afe7182016-08-13 14:08:17 -040072};
73
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -050074struct mapper_async_subtree
75{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050076 char* namespace;
77 char* interface;
78 void (*callback)(int, void*);
79 void* userdata;
80 sd_event* loop;
81 sd_bus* conn;
82 sd_bus_slot* slot;
83 sd_event_source* event_source;
Ed Tanous167e2372018-05-07 11:59:10 -070084 int finished;
85 int op;
86 int retry;
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -050087};
88
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050089static int async_wait_match_introspection_complete(sd_bus_message*, void*,
90 sd_bus_error*);
91static int async_wait_check_done(mapper_async_wait*);
92static void async_wait_done(int r, mapper_async_wait*);
93static int async_wait_get_objects(mapper_async_wait*);
94static int async_wait_getobject_callback(sd_bus_message*, void*, sd_bus_error*);
Brad Bishop2afe7182016-08-13 14:08:17 -040095
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050096static int async_subtree_match_callback(sd_bus_message*, void*, sd_bus_error*);
97static void async_subtree_done(int r, mapper_async_subtree*);
98static int async_subtree_getpaths(mapper_async_subtree*);
99static int async_subtree_getpaths_callback(sd_bus_message*, void*,
100 sd_bus_error*);
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500101
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500102static int sarraylen(char* array[])
Brad Bishop2afe7182016-08-13 14:08:17 -0400103{
Ed Tanous167e2372018-05-07 11:59:10 -0700104 int count = 0;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500105 char** p = array;
Brad Bishop2afe7182016-08-13 14:08:17 -0400106
Ed Tanous167e2372018-05-07 11:59:10 -0700107 while (*p != NULL)
108 {
109 ++count;
110 ++p;
111 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400112
Ed Tanous167e2372018-05-07 11:59:10 -0700113 return count;
Brad Bishop2afe7182016-08-13 14:08:17 -0400114}
115
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500116static void sarrayfree(char* array[])
Brad Bishop2afe7182016-08-13 14:08:17 -0400117{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500118 char** p = array;
Ed Tanous167e2372018-05-07 11:59:10 -0700119 while (*p != NULL)
120 {
121 free(*p);
122 ++p;
123 }
124 free(array);
Brad Bishop2afe7182016-08-13 14:08:17 -0400125}
126
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500127static char** sarraydup(char* array[])
Brad Bishop2afe7182016-08-13 14:08:17 -0400128{
Ed Tanous167e2372018-05-07 11:59:10 -0700129 int count = sarraylen(array);
130 int i;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500131 char** ret = NULL;
Brad Bishop2afe7182016-08-13 14:08:17 -0400132
Ed Tanous167e2372018-05-07 11:59:10 -0700133 ret = malloc(sizeof(*ret) * count);
134 if (!ret)
135 return NULL;
Brad Bishop2afe7182016-08-13 14:08:17 -0400136
Ed Tanous167e2372018-05-07 11:59:10 -0700137 for (i = 0; i < count; ++i)
138 {
139 ret[i] = strdup(array[i]);
140 if (!ret[i])
141 goto error;
142 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400143
Ed Tanous167e2372018-05-07 11:59:10 -0700144 return ret;
Brad Bishop2afe7182016-08-13 14:08:17 -0400145
146error:
Ed Tanous167e2372018-05-07 11:59:10 -0700147 sarrayfree(ret);
148 return NULL;
Brad Bishop2afe7182016-08-13 14:08:17 -0400149}
150
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500151static int async_wait_timeout_callback(sd_event_source* s, uint64_t usec,
152 void* userdata)
Brad Bishop3d468792016-09-20 15:39:38 -0400153{
Ed Tanous167e2372018-05-07 11:59:10 -0700154 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500155 struct async_wait_callback_data* data = userdata;
156 mapper_async_wait* wait = data->wait;
Brad Bishop3d468792016-09-20 15:39:38 -0400157
Ed Tanous167e2372018-05-07 11:59:10 -0700158 sd_event_source_unref(data->event_source);
159 r = sd_bus_call_method_async(wait->conn, NULL, MAPPER_BUSNAME, MAPPER_PATH,
160 MAPPER_INTERFACE, "GetObject",
161 async_wait_getobject_callback, data, "sas",
162 data->path, 0, NULL);
163 if (r < 0)
164 {
165 async_wait_done(r, wait);
166 free(data);
167 }
Brad Bishop3d468792016-09-20 15:39:38 -0400168
Ed Tanous167e2372018-05-07 11:59:10 -0700169 return 0;
Brad Bishop3d468792016-09-20 15:39:38 -0400170}
171
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500172static int async_wait_getobject_callback(sd_bus_message* m, void* userdata,
173 sd_bus_error* e)
Brad Bishop2afe7182016-08-13 14:08:17 -0400174{
Ed Tanous167e2372018-05-07 11:59:10 -0700175 int i, r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500176 struct async_wait_callback_data* data = userdata;
177 mapper_async_wait* wait = data->wait;
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700178 uint64_t next_retry;
Brad Bishop2afe7182016-08-13 14:08:17 -0400179
Ed Tanous167e2372018-05-07 11:59:10 -0700180 if (wait->finished)
181 goto exit;
Brad Bishop3d468792016-09-20 15:39:38 -0400182
Patrick Williamse82b0582020-11-16 16:25:20 -0600183 if (sd_bus_message_is_method_error(
184 m, "xyz.openbmc_project.Common.Error.ResourceNotFound"))
Ed Tanous167e2372018-05-07 11:59:10 -0700185 goto exit;
Brad Bishop8ccdaed2016-09-20 15:54:32 -0400186
Patrick Williamse82b0582020-11-16 16:25:20 -0600187 r = sd_bus_message_get_errno(m);
188
William A. Kennington III24829462018-06-15 10:10:25 -0700189 if ((r == EBUSY || r == ENOBUFS) && data->retry < mapper_busy_retries)
Ed Tanous167e2372018-05-07 11:59:10 -0700190 {
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700191 r = sd_event_now(wait->loop, CLOCK_MONOTONIC, &next_retry);
Ed Tanous167e2372018-05-07 11:59:10 -0700192 if (r < 0)
193 {
194 async_wait_done(r, wait);
195 goto exit;
196 }
Brad Bishop3d468792016-09-20 15:39:38 -0400197
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700198 next_retry += mapper_busy_delay_interval_usec * (1 << data->retry);
Ed Tanous167e2372018-05-07 11:59:10 -0700199 r = sd_event_add_time(wait->loop, &data->event_source, CLOCK_MONOTONIC,
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700200 next_retry, 0, async_wait_timeout_callback, data);
201 ++data->retry;
Ed Tanous167e2372018-05-07 11:59:10 -0700202 if (r < 0)
203 {
204 async_wait_done(r, wait);
205 goto exit;
206 }
Brad Bishop3d468792016-09-20 15:39:38 -0400207
Ed Tanous167e2372018-05-07 11:59:10 -0700208 return 0;
209 }
Brad Bishop3d468792016-09-20 15:39:38 -0400210
Ed Tanous167e2372018-05-07 11:59:10 -0700211 if (r)
212 {
213 async_wait_done(-r, wait);
214 goto exit;
215 }
Brad Bishop3d468792016-09-20 15:39:38 -0400216
Ed Tanous167e2372018-05-07 11:59:10 -0700217 for (i = 0; i < wait->count; ++i)
218 {
219 if (!strcmp(data->path, wait->objs[i]))
220 {
221 wait->status[i] = 1;
222 }
223 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400224
Ed Tanous167e2372018-05-07 11:59:10 -0700225 if (async_wait_check_done(wait))
226 async_wait_done(0, wait);
Brad Bishop2afe7182016-08-13 14:08:17 -0400227
Brad Bishop3d468792016-09-20 15:39:38 -0400228exit:
Ed Tanous167e2372018-05-07 11:59:10 -0700229 free(data);
230 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400231}
232
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500233static int async_wait_get_objects(mapper_async_wait* wait)
Brad Bishop2afe7182016-08-13 14:08:17 -0400234{
Ed Tanous167e2372018-05-07 11:59:10 -0700235 int i, r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500236 struct async_wait_callback_data* data = NULL;
Brad Bishop2afe7182016-08-13 14:08:17 -0400237
Ed Tanous167e2372018-05-07 11:59:10 -0700238 for (i = 0; i < wait->count; ++i)
239 {
240 if (wait->status[i])
241 continue;
242 data = malloc(sizeof(*data));
243 data->wait = wait;
244 data->path = wait->objs[i];
245 data->retry = 0;
246 data->event_source = NULL;
247 r = sd_bus_call_method_async(wait->conn, NULL, MAPPER_BUSNAME,
248 MAPPER_PATH, MAPPER_INTERFACE, "GetObject",
249 async_wait_getobject_callback, data, "sas",
250 wait->objs[i], 0, NULL);
251 if (r < 0)
252 {
253 free(data);
254 fprintf(stderr, "Error invoking method: %s\n", strerror(-r));
255 return r;
256 }
257 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400258
Ed Tanous167e2372018-05-07 11:59:10 -0700259 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400260}
261
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500262static int async_wait_match_introspection_complete(sd_bus_message* m, void* w,
263 sd_bus_error* e)
Brad Bishop2afe7182016-08-13 14:08:17 -0400264{
Ed Tanous167e2372018-05-07 11:59:10 -0700265 int r;
Brad Bishop2afe7182016-08-13 14:08:17 -0400266
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500267 mapper_async_wait* wait = w;
Ed Tanous167e2372018-05-07 11:59:10 -0700268 if (wait->finished)
269 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400270
Ed Tanous167e2372018-05-07 11:59:10 -0700271 r = async_wait_get_objects(wait);
272 if (r < 0)
273 async_wait_done(r, wait);
Brad Bishop2afe7182016-08-13 14:08:17 -0400274
Ed Tanous167e2372018-05-07 11:59:10 -0700275 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400276}
277
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500278static void async_wait_done(int r, mapper_async_wait* w)
Brad Bishop2afe7182016-08-13 14:08:17 -0400279{
Ed Tanous167e2372018-05-07 11:59:10 -0700280 if (w->finished)
281 return;
Brad Bishop2afe7182016-08-13 14:08:17 -0400282
Ed Tanous167e2372018-05-07 11:59:10 -0700283 w->finished = 1;
284 sd_bus_slot_unref(w->introspection_slot);
285 sd_bus_slot_unref(w->intf_slot);
Brad Bishop2afe7182016-08-13 14:08:17 -0400286
Ed Tanous167e2372018-05-07 11:59:10 -0700287 if (w->callback)
288 w->callback(r, w->userdata);
Brad Bishop2afe7182016-08-13 14:08:17 -0400289}
290
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500291static int async_wait_check_done(mapper_async_wait* w)
Brad Bishop2afe7182016-08-13 14:08:17 -0400292{
Ed Tanous167e2372018-05-07 11:59:10 -0700293 int i;
Brad Bishop2afe7182016-08-13 14:08:17 -0400294
Ed Tanous167e2372018-05-07 11:59:10 -0700295 if (w->finished)
296 return 1;
Brad Bishop2afe7182016-08-13 14:08:17 -0400297
Ed Tanous167e2372018-05-07 11:59:10 -0700298 for (i = 0; i < w->count; ++i)
299 if (!w->status[i])
300 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400301
Ed Tanous167e2372018-05-07 11:59:10 -0700302 return 1;
Brad Bishop2afe7182016-08-13 14:08:17 -0400303}
304
Brad Bishop75057c82021-08-03 15:22:02 -0400305_public_ void mapper_wait_async_free(mapper_async_wait* w)
Brad Bishop2afe7182016-08-13 14:08:17 -0400306{
Ed Tanous167e2372018-05-07 11:59:10 -0700307 free(w->status);
308 sarrayfree(w->objs);
309 free(w);
Brad Bishop2afe7182016-08-13 14:08:17 -0400310}
311
Brad Bishop75057c82021-08-03 15:22:02 -0400312_public_ int mapper_wait_async(sd_bus* conn, sd_event* loop, char* objs[],
313 void (*callback)(int, void*), void* userdata,
314 mapper_async_wait** w)
Brad Bishop2afe7182016-08-13 14:08:17 -0400315{
Ed Tanous167e2372018-05-07 11:59:10 -0700316 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500317 mapper_async_wait* wait = NULL;
Brad Bishop2afe7182016-08-13 14:08:17 -0400318
Ed Tanous167e2372018-05-07 11:59:10 -0700319 wait = malloc(sizeof(*wait));
320 if (!wait)
321 return -ENOMEM;
Brad Bishop2afe7182016-08-13 14:08:17 -0400322
Ed Tanous167e2372018-05-07 11:59:10 -0700323 memset(wait, 0, sizeof(*wait));
324 wait->conn = conn;
325 wait->loop = loop;
326 wait->callback = callback;
327 wait->userdata = userdata;
328 wait->count = sarraylen(objs);
329 if (!wait->count)
330 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400331
Ed Tanous167e2372018-05-07 11:59:10 -0700332 wait->objs = sarraydup(objs);
333 if (!wait->objs)
334 {
335 r = -ENOMEM;
336 goto free_wait;
337 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400338
Ed Tanous167e2372018-05-07 11:59:10 -0700339 wait->status = malloc(sizeof(*wait->status) * wait->count);
340 if (!wait->status)
341 {
342 r = -ENOMEM;
343 goto free_objs;
344 }
345 memset(wait->status, 0, sizeof(*wait->status) * wait->count);
Brad Bishop2afe7182016-08-13 14:08:17 -0400346
Ed Tanous167e2372018-05-07 11:59:10 -0700347 r = sd_bus_add_match(conn, &wait->introspection_slot,
348 async_wait_introspection_match,
349 async_wait_match_introspection_complete, wait);
350 if (r < 0)
351 {
352 fprintf(stderr, "Error adding match rule: %s\n", strerror(-r));
353 goto free_status;
354 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400355
Ed Tanous167e2372018-05-07 11:59:10 -0700356 r = sd_bus_add_match(conn, &wait->intf_slot,
357 async_wait_interfaces_added_match,
358 async_wait_match_introspection_complete, wait);
359 if (r < 0)
360 {
361 fprintf(stderr, "Error adding match rule: %s\n", strerror(-r));
362 goto unref_name_slot;
363 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400364
Ed Tanous167e2372018-05-07 11:59:10 -0700365 r = async_wait_get_objects(wait);
366 if (r < 0)
367 {
368 fprintf(stderr, "Error calling method: %s\n", strerror(-r));
369 goto unref_intf_slot;
370 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400371
Ed Tanous167e2372018-05-07 11:59:10 -0700372 *w = wait;
Brad Bishop2afe7182016-08-13 14:08:17 -0400373
Ed Tanous167e2372018-05-07 11:59:10 -0700374 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400375
376unref_intf_slot:
Ed Tanous167e2372018-05-07 11:59:10 -0700377 sd_bus_slot_unref(wait->intf_slot);
Brad Bishop2afe7182016-08-13 14:08:17 -0400378unref_name_slot:
Ed Tanous167e2372018-05-07 11:59:10 -0700379 sd_bus_slot_unref(wait->introspection_slot);
Brad Bishop2afe7182016-08-13 14:08:17 -0400380free_status:
Ed Tanous167e2372018-05-07 11:59:10 -0700381 free(wait->status);
Brad Bishop2afe7182016-08-13 14:08:17 -0400382free_objs:
Ed Tanous167e2372018-05-07 11:59:10 -0700383 sarrayfree(wait->objs);
Brad Bishop2afe7182016-08-13 14:08:17 -0400384free_wait:
Ed Tanous167e2372018-05-07 11:59:10 -0700385 free(wait);
Brad Bishop2afe7182016-08-13 14:08:17 -0400386
Ed Tanous167e2372018-05-07 11:59:10 -0700387 return r;
Brad Bishop2afe7182016-08-13 14:08:17 -0400388}
389
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500390static int async_subtree_timeout_callback(sd_event_source* s, uint64_t usec,
391 void* userdata)
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500392{
Ed Tanous167e2372018-05-07 11:59:10 -0700393 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500394 struct mapper_async_subtree* subtree = userdata;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500395
Ed Tanous167e2372018-05-07 11:59:10 -0700396 sd_event_source_unref(subtree->event_source);
397 r = sd_bus_call_method_async(
398 subtree->conn, NULL, MAPPER_BUSNAME, MAPPER_PATH, MAPPER_INTERFACE,
399 "GetSubTreePaths", async_subtree_getpaths_callback, subtree, "sias",
400 subtree->namespace, 0, 1, subtree->interface);
401 if (r < 0)
402 async_subtree_done(r, subtree);
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500403
Ed Tanous167e2372018-05-07 11:59:10 -0700404 return 0;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500405}
406
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500407static int async_subtree_getpaths_callback(sd_bus_message* m, void* userdata,
408 sd_bus_error* e)
Adriana Kobylak025d7952017-05-08 13:30:45 -0500409{
Ed Tanous167e2372018-05-07 11:59:10 -0700410 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500411 struct mapper_async_subtree* subtree = userdata;
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700412 uint64_t next_retry;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500413
Ed Tanous167e2372018-05-07 11:59:10 -0700414 if (subtree->finished)
415 goto exit;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500416
Ed Tanous167e2372018-05-07 11:59:10 -0700417 r = sd_bus_message_get_errno(m);
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500418
Patrick Williamse82b0582020-11-16 16:25:20 -0600419 if (sd_bus_message_is_method_error(
420 m, "xyz.openbmc_project.Common.Error.ResourceNotFound"))
Ed Tanous167e2372018-05-07 11:59:10 -0700421 {
422 if (subtree->op == MAPPER_OP_REMOVE)
423 r = 0;
424 else
425 goto exit;
426 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500427
William A. Kennington III24829462018-06-15 10:10:25 -0700428 if ((r == EBUSY || r == ENOBUFS) && subtree->retry < mapper_busy_retries)
Ed Tanous167e2372018-05-07 11:59:10 -0700429 {
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700430 r = sd_event_now(subtree->loop, CLOCK_MONOTONIC, &next_retry);
Ed Tanous167e2372018-05-07 11:59:10 -0700431 if (r < 0)
432 {
433 async_subtree_done(r, subtree);
434 goto exit;
435 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500436
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700437 next_retry += mapper_busy_delay_interval_usec * (1 << subtree->retry);
Ed Tanous167e2372018-05-07 11:59:10 -0700438 r = sd_event_add_time(subtree->loop, &subtree->event_source,
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700439 CLOCK_MONOTONIC, next_retry, 0,
Ed Tanous167e2372018-05-07 11:59:10 -0700440 async_subtree_timeout_callback, subtree);
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700441 ++subtree->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
Ed Tanous167e2372018-05-07 11:59:10 -0700448 return 0;
449 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500450
Ed Tanous167e2372018-05-07 11:59:10 -0700451 if (r)
452 {
453 async_subtree_done(-r, subtree);
454 goto exit;
455 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500456
Ed Tanous167e2372018-05-07 11:59:10 -0700457 if (subtree->op == MAPPER_OP_REMOVE)
458 {
William A. Kennington III20cbbfb2018-06-15 10:10:13 -0700459 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "s");
460 if (r < 0)
461 {
462 async_subtree_done(r, subtree);
463 goto exit;
464 }
465
466 r = sd_bus_message_at_end(m, false);
467 if (r < 0)
468 {
469 async_subtree_done(r, subtree);
470 goto exit;
471 }
472
Ed Tanous167e2372018-05-07 11:59:10 -0700473 /* For remove, operation is complete when the interface is not present
William A. Kennington III20cbbfb2018-06-15 10:10:13 -0700474 * we know it is empty if the returned array is empty
Ed Tanous167e2372018-05-07 11:59:10 -0700475 */
William A. Kennington III20cbbfb2018-06-15 10:10:13 -0700476 if (r)
Ed Tanous167e2372018-05-07 11:59:10 -0700477 async_subtree_done(0, subtree);
478 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500479
480exit:
Ed Tanous167e2372018-05-07 11:59:10 -0700481 return 0;
Adriana Kobylak025d7952017-05-08 13:30:45 -0500482}
483
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500484static int async_subtree_getpaths(mapper_async_subtree* subtree)
Adriana Kobylak025d7952017-05-08 13:30:45 -0500485{
Ed Tanous167e2372018-05-07 11:59:10 -0700486 int r = 0;
Adriana Kobylak025d7952017-05-08 13:30:45 -0500487
Ed Tanous167e2372018-05-07 11:59:10 -0700488 subtree->retry = 0;
489 subtree->event_source = NULL;
490 r = sd_bus_call_method_async(
491 subtree->conn, NULL, MAPPER_BUSNAME, MAPPER_PATH, MAPPER_INTERFACE,
492 "GetSubTreePaths", async_subtree_getpaths_callback, subtree, "sias",
493 subtree->namespace, 0, 1, subtree->interface);
494 if (r < 0)
495 {
496 fprintf(stderr, "Error invoking method: %s\n", strerror(-r));
497 return r;
498 }
Adriana Kobylak025d7952017-05-08 13:30:45 -0500499
Ed Tanous167e2372018-05-07 11:59:10 -0700500 return 0;
Adriana Kobylak025d7952017-05-08 13:30:45 -0500501}
502
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500503static int async_subtree_match_callback(sd_bus_message* m, void* t,
504 sd_bus_error* e)
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500505{
Ed Tanous167e2372018-05-07 11:59:10 -0700506 int r;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500507
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500508 mapper_async_subtree* subtree = t;
Ed Tanous167e2372018-05-07 11:59:10 -0700509 if (subtree->finished)
510 return 0;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500511
Ed Tanous167e2372018-05-07 11:59:10 -0700512 r = async_subtree_getpaths(subtree);
513 if (r < 0)
514 async_subtree_done(r, subtree);
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500515
Ed Tanous167e2372018-05-07 11:59:10 -0700516 return 0;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500517}
518
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500519static void async_subtree_done(int r, mapper_async_subtree* t)
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500520{
Ed Tanous167e2372018-05-07 11:59:10 -0700521 if (t->finished)
522 return;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500523
Ed Tanous167e2372018-05-07 11:59:10 -0700524 t->finished = 1;
525 sd_bus_slot_unref(t->slot);
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500526
Ed Tanous167e2372018-05-07 11:59:10 -0700527 if (t->callback)
528 t->callback(r, t->userdata);
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500529}
530
Brad Bishop75057c82021-08-03 15:22:02 -0400531_public_ int mapper_subtree_async(sd_bus* conn, sd_event* loop, char* namespace,
532 char* interface, void (*callback)(int, void*),
533 void* userdata, mapper_async_subtree** t,
534 int op)
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500535{
Ed Tanous167e2372018-05-07 11:59:10 -0700536 int r = 0;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500537 mapper_async_subtree* subtree = NULL;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500538
Ed Tanous167e2372018-05-07 11:59:10 -0700539 subtree = malloc(sizeof(*subtree));
540 if (!subtree)
541 return -ENOMEM;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500542
Ed Tanous167e2372018-05-07 11:59:10 -0700543 memset(subtree, 0, sizeof(*subtree));
544 subtree->conn = conn;
545 subtree->loop = loop;
546 subtree->namespace = namespace;
547 subtree->interface = interface;
548 subtree->callback = callback;
549 subtree->userdata = userdata;
550 subtree->op = op;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500551
Ed Tanous167e2372018-05-07 11:59:10 -0700552 if (subtree->op == MAPPER_OP_REMOVE)
553 {
554 r = sd_bus_add_match(conn, &subtree->slot, interfaces_removed_match,
555 async_subtree_match_callback, subtree);
556 if (r < 0)
557 {
558 fprintf(stderr, "Error adding match rule: %s\n", strerror(-r));
559 goto unref_slot;
560 }
561 }
562 else
563 {
564 /* Operation not supported */
565 r = -EINVAL;
566 goto free_subtree;
567 }
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500568
Ed Tanous167e2372018-05-07 11:59:10 -0700569 r = async_subtree_getpaths(subtree);
570 if (r < 0)
571 {
572 fprintf(stderr, "Error calling method: %s\n", strerror(-r));
573 goto unref_slot;
574 }
Adriana Kobylak025d7952017-05-08 13:30:45 -0500575
Ed Tanous167e2372018-05-07 11:59:10 -0700576 *t = subtree;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500577
Ed Tanous167e2372018-05-07 11:59:10 -0700578 return 0;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500579
580unref_slot:
Ed Tanous167e2372018-05-07 11:59:10 -0700581 sd_bus_slot_unref(subtree->slot);
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500582free_subtree:
Ed Tanous167e2372018-05-07 11:59:10 -0700583 free(subtree);
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500584
Ed Tanous167e2372018-05-07 11:59:10 -0700585 return r;
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500586}
587
Brad Bishop75057c82021-08-03 15:22:02 -0400588_public_ int mapper_get_object(sd_bus* conn, const char* obj,
589 sd_bus_message** reply)
Brad Bishop62ece2b2016-07-25 09:00:51 -0400590{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500591 sd_bus_message* request = NULL;
Ed Tanous167e2372018-05-07 11:59:10 -0700592 int r, retry = 0;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400593
Ed Tanous167e2372018-05-07 11:59:10 -0700594 r = sd_bus_message_new_method_call(conn, &request, MAPPER_BUSNAME,
595 MAPPER_PATH, MAPPER_INTERFACE,
596 "GetObject");
597 if (r < 0)
598 goto exit;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400599
Ed Tanous167e2372018-05-07 11:59:10 -0700600 r = sd_bus_message_append(request, "s", obj);
601 if (r < 0)
602 goto exit;
603 r = sd_bus_message_append(request, "as", 0, NULL);
604 if (r < 0)
605 goto exit;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400606
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700607 while (true)
Ed Tanous167e2372018-05-07 11:59:10 -0700608 {
William A. Kennington III24829462018-06-15 10:10:25 -0700609 r = sd_bus_call(conn, request, 0, NULL, reply);
610 if (r == -EBUSY || r == -ENOBUFS)
Ed Tanous167e2372018-05-07 11:59:10 -0700611 {
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700612 if (retry >= mapper_busy_retries)
613 break;
Brad Bishop3d468792016-09-20 15:39:38 -0400614
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700615 usleep(mapper_busy_delay_interval_usec * (1 << retry));
616 ++retry;
Ed Tanous167e2372018-05-07 11:59:10 -0700617 continue;
618 }
619 break;
620 }
Brad Bishop3d468792016-09-20 15:39:38 -0400621
Ed Tanous167e2372018-05-07 11:59:10 -0700622 if (r < 0)
623 goto exit;
Brad Bishop3d468792016-09-20 15:39:38 -0400624
625exit:
Ed Tanous167e2372018-05-07 11:59:10 -0700626 sd_bus_message_unref(request);
Brad Bishop3d468792016-09-20 15:39:38 -0400627
Ed Tanous167e2372018-05-07 11:59:10 -0700628 return r;
Brad Bishop3d468792016-09-20 15:39:38 -0400629}
630
Brad Bishop75057c82021-08-03 15:22:02 -0400631_public_ int mapper_get_service(sd_bus* conn, const char* obj, char** service)
Brad Bishop3d468792016-09-20 15:39:38 -0400632{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500633 sd_bus_message* reply = NULL;
634 const char* tmp;
Ed Tanous167e2372018-05-07 11:59:10 -0700635 int r;
Brad Bishop3d468792016-09-20 15:39:38 -0400636
Ed Tanous167e2372018-05-07 11:59:10 -0700637 r = mapper_get_object(conn, obj, &reply);
638 if (r < 0)
639 goto exit;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400640
Ed Tanous167e2372018-05-07 11:59:10 -0700641 r = sd_bus_message_enter_container(reply, 0, NULL);
642 if (r < 0)
643 goto exit;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400644
Ed Tanous167e2372018-05-07 11:59:10 -0700645 r = sd_bus_message_enter_container(reply, 0, NULL);
646 if (r < 0)
647 goto exit;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400648
Ed Tanous167e2372018-05-07 11:59:10 -0700649 r = sd_bus_message_read(reply, "s", &tmp);
650 if (r < 0)
651 goto exit;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400652
Ed Tanous167e2372018-05-07 11:59:10 -0700653 *service = strdup(tmp);
Brad Bishop62ece2b2016-07-25 09:00:51 -0400654
655exit:
Ed Tanous167e2372018-05-07 11:59:10 -0700656 sd_bus_message_unref(reply);
Brad Bishop62ece2b2016-07-25 09:00:51 -0400657
Ed Tanous167e2372018-05-07 11:59:10 -0700658 return r;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400659}