1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
39 #include "bus-internal.h"
40 #include "bus-message.h"
42 #include "bus-socket.h"
43 #include "bus-kernel.h"
44 #include "bus-control.h"
45 #include "bus-introspect.h"
46 #include "bus-signature.h"
48 static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec);
50 static void bus_close_fds(sd_bus *b) {
54 close_nointr_nofail(b->input_fd);
56 if (b->output_fd >= 0 && b->output_fd != b->input_fd)
57 close_nointr_nofail(b->output_fd);
59 b->input_fd = b->output_fd = -1;
62 static void bus_node_destroy(sd_bus *b, struct node *n) {
63 struct node_callback *c;
64 struct node_vtable *v;
65 struct node_enumerator *e;
73 bus_node_destroy(b, n->child);
75 while ((c = n->callbacks)) {
76 LIST_REMOVE(struct node_callback, callbacks, n->callbacks, c);
80 while ((v = n->vtables)) {
81 LIST_REMOVE(struct node_vtable, vtables, n->vtables, v);
86 while ((e = n->enumerators)) {
87 LIST_REMOVE(struct node_enumerator, enumerators, n->enumerators, e);
92 LIST_REMOVE(struct node, siblings, n->parent->child, n);
94 assert_se(hashmap_remove(b->nodes, n->path) == n);
99 static void bus_free(sd_bus *b) {
100 struct filter_callback *f;
109 munmap(b->kdbus_buffer, KDBUS_POOL_SIZE);
112 free(b->unique_name);
113 free(b->auth_buffer);
118 strv_free(b->exec_argv);
120 close_many(b->fds, b->n_fds);
123 for (i = 0; i < b->rqueue_size; i++)
124 sd_bus_message_unref(b->rqueue[i]);
127 for (i = 0; i < b->wqueue_size; i++)
128 sd_bus_message_unref(b->wqueue[i]);
131 hashmap_free_free(b->reply_callbacks);
132 prioq_free(b->reply_callbacks_prioq);
134 while ((f = b->filter_callbacks)) {
135 LIST_REMOVE(struct filter_callback, callbacks, b->filter_callbacks, f);
139 bus_match_free(&b->match_callbacks);
141 hashmap_free_free(b->vtable_methods);
142 hashmap_free_free(b->vtable_properties);
144 while ((n = hashmap_first(b->nodes)))
145 bus_node_destroy(b, n);
147 hashmap_free(b->nodes);
149 bus_kernel_flush_memfd(b);
151 assert_se(pthread_mutex_destroy(&b->memfd_cache_mutex) == 0);
156 int sd_bus_new(sd_bus **ret) {
166 r->n_ref = REFCNT_INIT;
167 r->input_fd = r->output_fd = -1;
168 r->message_version = 1;
169 r->hello_flags |= KDBUS_HELLO_ACCEPT_FD;
170 r->original_pid = getpid();
172 assert_se(pthread_mutex_init(&r->memfd_cache_mutex, NULL) == 0);
174 /* We guarantee that wqueue always has space for at least one
176 r->wqueue = new(sd_bus_message*, 1);
186 int sd_bus_set_address(sd_bus *bus, const char *address) {
191 if (bus->state != BUS_UNSET)
195 if (bus_pid_changed(bus))
208 int sd_bus_set_fd(sd_bus *bus, int input_fd, int output_fd) {
211 if (bus->state != BUS_UNSET)
217 if (bus_pid_changed(bus))
220 bus->input_fd = input_fd;
221 bus->output_fd = output_fd;
225 int sd_bus_set_exec(sd_bus *bus, const char *path, char *const argv[]) {
230 if (bus->state != BUS_UNSET)
234 if (strv_isempty(argv))
236 if (bus_pid_changed(bus))
249 free(bus->exec_path);
250 strv_free(bus->exec_argv);
258 int sd_bus_set_bus_client(sd_bus *bus, int b) {
261 if (bus->state != BUS_UNSET)
263 if (bus_pid_changed(bus))
266 bus->bus_client = !!b;
270 int sd_bus_negotiate_fds(sd_bus *bus, int b) {
273 if (bus->state != BUS_UNSET)
275 if (bus_pid_changed(bus))
278 SET_FLAG(bus->hello_flags, KDBUS_HELLO_ACCEPT_FD, b);
282 int sd_bus_negotiate_attach_comm(sd_bus *bus, int b) {
285 if (bus->state != BUS_UNSET)
287 if (bus_pid_changed(bus))
290 SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_COMM, b);
294 int sd_bus_negotiate_attach_exe(sd_bus *bus, int b) {
297 if (bus->state != BUS_UNSET)
299 if (bus_pid_changed(bus))
302 SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_EXE, b);
306 int sd_bus_negotiate_attach_cmdline(sd_bus *bus, int b) {
309 if (bus->state != BUS_UNSET)
311 if (bus_pid_changed(bus))
314 SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_CMDLINE, b);
318 int sd_bus_negotiate_attach_cgroup(sd_bus *bus, int b) {
321 if (bus->state != BUS_UNSET)
323 if (bus_pid_changed(bus))
326 SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_CGROUP, b);
330 int sd_bus_negotiate_attach_caps(sd_bus *bus, int b) {
333 if (bus->state != BUS_UNSET)
335 if (bus_pid_changed(bus))
338 SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_CAPS, b);
342 int sd_bus_negotiate_attach_selinux_context(sd_bus *bus, int b) {
345 if (bus->state != BUS_UNSET)
347 if (bus_pid_changed(bus))
350 SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_SECLABEL, b);
354 int sd_bus_negotiate_attach_audit(sd_bus *bus, int b) {
357 if (bus->state != BUS_UNSET)
359 if (bus_pid_changed(bus))
362 SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_AUDIT, b);
366 int sd_bus_set_server(sd_bus *bus, int b, sd_id128_t server_id) {
369 if (!b && !sd_id128_equal(server_id, SD_ID128_NULL))
371 if (bus->state != BUS_UNSET)
373 if (bus_pid_changed(bus))
376 bus->is_server = !!b;
377 bus->server_id = server_id;
381 int sd_bus_set_anonymous(sd_bus *bus, int b) {
384 if (bus->state != BUS_UNSET)
386 if (bus_pid_changed(bus))
389 bus->anonymous_auth = !!b;
393 static int hello_callback(sd_bus *bus, sd_bus_message *reply, void *userdata) {
398 assert(bus->state == BUS_HELLO);
401 r = bus_message_to_errno(reply);
405 r = sd_bus_message_read(reply, "s", &s);
409 if (!service_name_is_valid(s) || s[0] != ':')
412 bus->unique_name = strdup(s);
413 if (!bus->unique_name)
416 bus->state = BUS_RUNNING;
421 static int bus_send_hello(sd_bus *bus) {
422 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
427 if (!bus->bus_client || bus->is_kernel)
430 r = sd_bus_message_new_method_call(
432 "org.freedesktop.DBus",
434 "org.freedesktop.DBus",
440 return sd_bus_send_with_reply(bus, m, hello_callback, NULL, 0, &bus->hello_serial);
443 int bus_start_running(sd_bus *bus) {
446 if (bus->bus_client && !bus->is_kernel) {
447 bus->state = BUS_HELLO;
451 bus->state = BUS_RUNNING;
455 static int parse_address_key(const char **p, const char *key, char **value) {
466 if (strncmp(*p, key, l) != 0)
479 while (*a != ';' && *a != ',' && *a != 0) {
497 c = (char) ((x << 4) | y);
504 t = realloc(r, n + 2);
532 static void skip_address_key(const char **p) {
536 *p += strcspn(*p, ",");
542 static int parse_unix_address(sd_bus *b, const char **p, char **guid) {
543 _cleanup_free_ char *path = NULL, *abstract = NULL;
552 while (**p != 0 && **p != ';') {
553 r = parse_address_key(p, "guid", guid);
559 r = parse_address_key(p, "path", &path);
565 r = parse_address_key(p, "abstract", &abstract);
574 if (!path && !abstract)
577 if (path && abstract)
582 if (l > sizeof(b->sockaddr.un.sun_path))
585 b->sockaddr.un.sun_family = AF_UNIX;
586 strncpy(b->sockaddr.un.sun_path, path, sizeof(b->sockaddr.un.sun_path));
587 b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + l;
588 } else if (abstract) {
589 l = strlen(abstract);
590 if (l > sizeof(b->sockaddr.un.sun_path) - 1)
593 b->sockaddr.un.sun_family = AF_UNIX;
594 b->sockaddr.un.sun_path[0] = 0;
595 strncpy(b->sockaddr.un.sun_path+1, abstract, sizeof(b->sockaddr.un.sun_path)-1);
596 b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + 1 + l;
602 static int parse_tcp_address(sd_bus *b, const char **p, char **guid) {
603 _cleanup_free_ char *host = NULL, *port = NULL, *family = NULL;
605 struct addrinfo *result, hints = {
606 .ai_socktype = SOCK_STREAM,
607 .ai_flags = AI_ADDRCONFIG,
615 while (**p != 0 && **p != ';') {
616 r = parse_address_key(p, "guid", guid);
622 r = parse_address_key(p, "host", &host);
628 r = parse_address_key(p, "port", &port);
634 r = parse_address_key(p, "family", &family);
647 if (streq(family, "ipv4"))
648 hints.ai_family = AF_INET;
649 else if (streq(family, "ipv6"))
650 hints.ai_family = AF_INET6;
655 r = getaddrinfo(host, port, &hints, &result);
659 return -EADDRNOTAVAIL;
661 memcpy(&b->sockaddr, result->ai_addr, result->ai_addrlen);
662 b->sockaddr_size = result->ai_addrlen;
664 freeaddrinfo(result);
669 static int parse_exec_address(sd_bus *b, const char **p, char **guid) {
671 unsigned n_argv = 0, j;
680 while (**p != 0 && **p != ';') {
681 r = parse_address_key(p, "guid", guid);
687 r = parse_address_key(p, "path", &path);
693 if (startswith(*p, "argv")) {
697 ul = strtoul(*p + 4, (char**) p, 10);
698 if (errno > 0 || **p != '=' || ul > 256) {
708 x = realloc(argv, sizeof(char*) * (ul + 2));
714 memset(x + n_argv, 0, sizeof(char*) * (ul - n_argv + 2));
720 r = parse_address_key(p, NULL, argv + ul);
735 /* Make sure there are no holes in the array, with the
736 * exception of argv[0] */
737 for (j = 1; j < n_argv; j++)
743 if (argv && argv[0] == NULL) {
744 argv[0] = strdup(path);
756 for (j = 0; j < n_argv; j++)
764 static int parse_kernel_address(sd_bus *b, const char **p, char **guid) {
765 _cleanup_free_ char *path = NULL;
773 while (**p != 0 && **p != ';') {
774 r = parse_address_key(p, "guid", guid);
780 r = parse_address_key(p, "path", &path);
799 static void bus_reset_parsed_address(sd_bus *b) {
803 b->sockaddr_size = 0;
804 strv_free(b->exec_argv);
808 b->server_id = SD_ID128_NULL;
813 static int bus_parse_next_address(sd_bus *b) {
814 _cleanup_free_ char *guid = NULL;
822 if (b->address[b->address_index] == 0)
825 bus_reset_parsed_address(b);
827 a = b->address + b->address_index;
836 if (startswith(a, "unix:")) {
839 r = parse_unix_address(b, &a, &guid);
844 } else if (startswith(a, "tcp:")) {
847 r = parse_tcp_address(b, &a, &guid);
853 } else if (startswith(a, "unixexec:")) {
856 r = parse_exec_address(b, &a, &guid);
862 } else if (startswith(a, "kernel:")) {
865 r = parse_kernel_address(b, &a, &guid);
878 r = sd_id128_from_string(guid, &b->server_id);
883 b->address_index = a - b->address;
887 static int bus_start_address(sd_bus *b) {
895 if (b->sockaddr.sa.sa_family != AF_UNSPEC) {
897 r = bus_socket_connect(b);
901 b->last_connect_error = -r;
903 } else if (b->exec_path) {
905 r = bus_socket_exec(b);
909 b->last_connect_error = -r;
910 } else if (b->kernel) {
912 r = bus_kernel_connect(b);
916 b->last_connect_error = -r;
919 r = bus_parse_next_address(b);
923 return b->last_connect_error ? -b->last_connect_error : -ECONNREFUSED;
927 int bus_next_address(sd_bus *b) {
930 bus_reset_parsed_address(b);
931 return bus_start_address(b);
934 static int bus_start_fd(sd_bus *b) {
939 assert(b->input_fd >= 0);
940 assert(b->output_fd >= 0);
942 r = fd_nonblock(b->input_fd, true);
946 r = fd_cloexec(b->input_fd, true);
950 if (b->input_fd != b->output_fd) {
951 r = fd_nonblock(b->output_fd, true);
955 r = fd_cloexec(b->output_fd, true);
960 if (fstat(b->input_fd, &st) < 0)
963 if (S_ISCHR(b->input_fd))
964 return bus_kernel_take_fd(b);
966 return bus_socket_take_fd(b);
969 int sd_bus_start(sd_bus *bus) {
974 if (bus->state != BUS_UNSET)
976 if (bus_pid_changed(bus))
979 bus->state = BUS_OPENING;
981 if (bus->is_server && bus->bus_client)
984 if (bus->input_fd >= 0)
985 r = bus_start_fd(bus);
986 else if (bus->address || bus->sockaddr.sa.sa_family != AF_UNSPEC || bus->exec_path || bus->kernel)
987 r = bus_start_address(bus);
994 return bus_send_hello(bus);
997 int sd_bus_open_system(sd_bus **ret) {
1009 e = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
1011 r = sd_bus_set_address(b, e);
1015 b->sockaddr.un.sun_family = AF_UNIX;
1016 strncpy(b->sockaddr.un.sun_path, "/run/dbus/system_bus_socket", sizeof(b->sockaddr.un.sun_path));
1017 b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/dbus/system_bus_socket") - 1;
1020 b->bus_client = true;
1022 r = sd_bus_start(b);
1034 int sd_bus_open_user(sd_bus **ret) {
1047 e = secure_getenv("DBUS_SESSION_BUS_ADDRESS");
1049 r = sd_bus_set_address(b, e);
1053 e = secure_getenv("XDG_RUNTIME_DIR");
1060 if (l + 4 > sizeof(b->sockaddr.un.sun_path)) {
1065 b->sockaddr.un.sun_family = AF_UNIX;
1066 memcpy(mempcpy(b->sockaddr.un.sun_path, e, l), "/bus", 4);
1067 b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + l + 4;
1070 b->bus_client = true;
1072 r = sd_bus_start(b);
1084 void sd_bus_close(sd_bus *bus) {
1087 if (bus->state == BUS_CLOSED)
1089 if (bus_pid_changed(bus))
1092 bus->state = BUS_CLOSED;
1094 if (!bus->is_kernel)
1097 /* We'll leave the fd open in case this is a kernel bus, since
1098 * there might still be memblocks around that reference this
1099 * bus, and they might need to invoke the
1100 * KDBUS_CMD_MSG_RELEASE ioctl on the fd when they are
1104 sd_bus *sd_bus_ref(sd_bus *bus) {
1108 assert_se(REFCNT_INC(bus->n_ref) >= 2);
1113 sd_bus *sd_bus_unref(sd_bus *bus) {
1117 if (REFCNT_DEC(bus->n_ref) <= 0)
1123 int sd_bus_is_open(sd_bus *bus) {
1126 if (bus_pid_changed(bus))
1129 return BUS_IS_OPEN(bus->state);
1132 int sd_bus_can_send(sd_bus *bus, char type) {
1137 if (bus->state == BUS_UNSET)
1139 if (bus_pid_changed(bus))
1142 if (type == SD_BUS_TYPE_UNIX_FD) {
1143 if (!(bus->hello_flags & KDBUS_HELLO_ACCEPT_FD))
1146 r = bus_ensure_running(bus);
1150 return bus->can_fds;
1153 return bus_type_is_valid(type);
1156 int sd_bus_get_server_id(sd_bus *bus, sd_id128_t *server_id) {
1163 if (bus_pid_changed(bus))
1166 r = bus_ensure_running(bus);
1170 *server_id = bus->server_id;
1174 static int bus_seal_message(sd_bus *b, sd_bus_message *m) {
1177 if (m->header->version > b->message_version)
1183 return bus_message_seal(m, ++b->serial);
1186 static int dispatch_wqueue(sd_bus *bus) {
1190 assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
1192 while (bus->wqueue_size > 0) {
1195 r = bus_kernel_write_message(bus, bus->wqueue[0]);
1197 r = bus_socket_write_message(bus, bus->wqueue[0], &bus->windex);
1203 /* Didn't do anything this time */
1205 else if (bus->is_kernel || bus->windex >= BUS_MESSAGE_SIZE(bus->wqueue[0])) {
1206 /* Fully written. Let's drop the entry from
1209 * This isn't particularly optimized, but
1210 * well, this is supposed to be our worst-case
1211 * buffer only, and the socket buffer is
1212 * supposed to be our primary buffer, and if
1213 * it got full, then all bets are off
1216 sd_bus_message_unref(bus->wqueue[0]);
1217 bus->wqueue_size --;
1218 memmove(bus->wqueue, bus->wqueue + 1, sizeof(sd_bus_message*) * bus->wqueue_size);
1228 static int dispatch_rqueue(sd_bus *bus, sd_bus_message **m) {
1229 sd_bus_message *z = NULL;
1234 assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
1236 if (bus->rqueue_size > 0) {
1237 /* Dispatch a queued message */
1239 *m = bus->rqueue[0];
1240 bus->rqueue_size --;
1241 memmove(bus->rqueue, bus->rqueue + 1, sizeof(sd_bus_message*) * bus->rqueue_size);
1245 /* Try to read a new message */
1248 r = bus_kernel_read_message(bus, &z);
1250 r = bus_socket_read_message(bus, &z);
1266 int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *serial) {
1271 if (!BUS_IS_OPEN(bus->state))
1275 if (bus_pid_changed(bus))
1279 r = sd_bus_can_send(bus, SD_BUS_TYPE_UNIX_FD);
1286 /* If the serial number isn't kept, then we know that no reply
1288 if (!serial && !m->sealed)
1289 m->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
1291 r = bus_seal_message(bus, m);
1295 /* If this is a reply and no reply was requested, then let's
1296 * suppress this, if we can */
1297 if (m->dont_send && !serial)
1300 if ((bus->state == BUS_RUNNING || bus->state == BUS_HELLO) && bus->wqueue_size <= 0) {
1304 r = bus_kernel_write_message(bus, m);
1306 r = bus_socket_write_message(bus, m, &idx);
1311 } else if (!bus->is_kernel && idx < BUS_MESSAGE_SIZE(m)) {
1312 /* Wasn't fully written. So let's remember how
1313 * much was written. Note that the first entry
1314 * of the wqueue array is always allocated so
1315 * that we always can remember how much was
1317 bus->wqueue[0] = sd_bus_message_ref(m);
1318 bus->wqueue_size = 1;
1324 /* Just append it to the queue. */
1326 if (bus->wqueue_size >= BUS_WQUEUE_MAX)
1329 q = realloc(bus->wqueue, sizeof(sd_bus_message*) * (bus->wqueue_size + 1));
1334 q[bus->wqueue_size ++] = sd_bus_message_ref(m);
1338 *serial = BUS_MESSAGE_SERIAL(m);
1343 static usec_t calc_elapse(uint64_t usec) {
1344 if (usec == (uint64_t) -1)
1348 usec = BUS_DEFAULT_TIMEOUT;
1350 return now(CLOCK_MONOTONIC) + usec;
1353 static int timeout_compare(const void *a, const void *b) {
1354 const struct reply_callback *x = a, *y = b;
1356 if (x->timeout != 0 && y->timeout == 0)
1359 if (x->timeout == 0 && y->timeout != 0)
1362 if (x->timeout < y->timeout)
1365 if (x->timeout > y->timeout)
1371 int sd_bus_send_with_reply(
1374 sd_bus_message_handler_t callback,
1379 struct reply_callback *c;
1384 if (!BUS_IS_OPEN(bus->state))
1390 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
1392 if (m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
1394 if (bus_pid_changed(bus))
1397 r = hashmap_ensure_allocated(&bus->reply_callbacks, uint64_hash_func, uint64_compare_func);
1401 if (usec != (uint64_t) -1) {
1402 r = prioq_ensure_allocated(&bus->reply_callbacks_prioq, timeout_compare);
1407 r = bus_seal_message(bus, m);
1411 c = new0(struct reply_callback, 1);
1415 c->callback = callback;
1416 c->userdata = userdata;
1417 c->serial = BUS_MESSAGE_SERIAL(m);
1418 c->timeout = calc_elapse(usec);
1420 r = hashmap_put(bus->reply_callbacks, &c->serial, c);
1426 if (c->timeout != 0) {
1427 r = prioq_put(bus->reply_callbacks_prioq, c, &c->prioq_idx);
1430 sd_bus_send_with_reply_cancel(bus, c->serial);
1435 r = sd_bus_send(bus, m, serial);
1437 sd_bus_send_with_reply_cancel(bus, c->serial);
1444 int sd_bus_send_with_reply_cancel(sd_bus *bus, uint64_t serial) {
1445 struct reply_callback *c;
1451 if (bus_pid_changed(bus))
1454 c = hashmap_remove(bus->reply_callbacks, &serial);
1458 if (c->timeout != 0)
1459 prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
1465 int bus_ensure_running(sd_bus *bus) {
1470 if (bus->state == BUS_UNSET || bus->state == BUS_CLOSED)
1472 if (bus->state == BUS_RUNNING)
1476 r = sd_bus_process(bus, NULL);
1479 if (bus->state == BUS_RUNNING)
1484 r = sd_bus_wait(bus, (uint64_t) -1);
1490 int sd_bus_send_with_reply_and_block(
1494 sd_bus_error *error,
1495 sd_bus_message **reply) {
1504 if (!BUS_IS_OPEN(bus->state))
1508 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
1510 if (m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
1512 if (bus_error_is_dirty(error))
1514 if (bus_pid_changed(bus))
1517 r = bus_ensure_running(bus);
1521 r = sd_bus_send(bus, m, &serial);
1525 timeout = calc_elapse(usec);
1529 sd_bus_message *incoming = NULL;
1534 if (bus->rqueue_size >= BUS_RQUEUE_MAX)
1537 /* Make sure there's room for queuing this
1538 * locally, before we read the message */
1540 q = realloc(bus->rqueue, (bus->rqueue_size + 1) * sizeof(sd_bus_message*));
1549 r = bus_kernel_read_message(bus, &incoming);
1551 r = bus_socket_read_message(bus, &incoming);
1556 if (incoming->reply_serial == serial) {
1557 /* Found a match! */
1559 if (incoming->header->type == SD_BUS_MESSAGE_TYPE_METHOD_RETURN) {
1564 sd_bus_message_unref(incoming);
1569 if (incoming->header->type == SD_BUS_MESSAGE_TYPE_METHOD_ERROR) {
1572 r = sd_bus_error_copy(error, &incoming->error);
1574 sd_bus_message_unref(incoming);
1578 k = bus_error_to_errno(&incoming->error);
1579 sd_bus_message_unref(incoming);
1583 sd_bus_message_unref(incoming);
1587 /* There's already guaranteed to be room for
1588 * this, so need to resize things here */
1589 bus->rqueue[bus->rqueue_size ++] = incoming;
1592 /* Try to read more, right-away */
1601 n = now(CLOCK_MONOTONIC);
1607 left = (uint64_t) -1;
1609 r = bus_poll(bus, true, left);
1613 r = dispatch_wqueue(bus);
1619 int sd_bus_get_fd(sd_bus *bus) {
1622 if (!BUS_IS_OPEN(bus->state))
1624 if (bus->input_fd != bus->output_fd)
1626 if (bus_pid_changed(bus))
1629 return bus->input_fd;
1632 int sd_bus_get_events(sd_bus *bus) {
1637 if (!BUS_IS_OPEN(bus->state))
1639 if (bus_pid_changed(bus))
1642 if (bus->state == BUS_OPENING)
1644 else if (bus->state == BUS_AUTHENTICATING) {
1646 if (bus_socket_auth_needs_write(bus))
1651 } else if (bus->state == BUS_RUNNING || bus->state == BUS_HELLO) {
1652 if (bus->rqueue_size <= 0)
1654 if (bus->wqueue_size > 0)
1661 int sd_bus_get_timeout(sd_bus *bus, uint64_t *timeout_usec) {
1662 struct reply_callback *c;
1668 if (!BUS_IS_OPEN(bus->state))
1670 if (bus_pid_changed(bus))
1673 if (bus->state == BUS_AUTHENTICATING) {
1674 *timeout_usec = bus->auth_timeout;
1678 if (bus->state != BUS_RUNNING && bus->state != BUS_HELLO) {
1679 *timeout_usec = (uint64_t) -1;
1683 c = prioq_peek(bus->reply_callbacks_prioq);
1685 *timeout_usec = (uint64_t) -1;
1689 *timeout_usec = c->timeout;
1693 static int process_timeout(sd_bus *bus) {
1694 _cleanup_bus_message_unref_ sd_bus_message* m = NULL;
1695 struct reply_callback *c;
1701 c = prioq_peek(bus->reply_callbacks_prioq);
1705 n = now(CLOCK_MONOTONIC);
1709 r = bus_message_new_synthetic_error(
1712 &SD_BUS_ERROR_MAKE("org.freedesktop.DBus.Error.Timeout", "Timed out"),
1717 assert_se(prioq_pop(bus->reply_callbacks_prioq) == c);
1718 hashmap_remove(bus->reply_callbacks, &c->serial);
1720 r = c->callback(bus, m, c->userdata);
1723 return r < 0 ? r : 1;
1726 static int process_hello(sd_bus *bus, sd_bus_message *m) {
1730 if (bus->state != BUS_HELLO)
1733 /* Let's make sure the first message on the bus is the HELLO
1734 * reply. But note that we don't actually parse the message
1735 * here (we leave that to the usual handling), we just verify
1736 * we don't let any earlier msg through. */
1738 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_RETURN &&
1739 m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_ERROR)
1742 if (m->reply_serial != bus->hello_serial)
1748 static int process_reply(sd_bus *bus, sd_bus_message *m) {
1749 struct reply_callback *c;
1755 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_RETURN &&
1756 m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_ERROR)
1759 c = hashmap_remove(bus->reply_callbacks, &m->reply_serial);
1763 if (c->timeout != 0)
1764 prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
1766 r = sd_bus_message_rewind(m, true);
1770 r = c->callback(bus, m, c->userdata);
1776 static int process_filter(sd_bus *bus, sd_bus_message *m) {
1777 struct filter_callback *l;
1784 bus->filter_callbacks_modified = false;
1786 LIST_FOREACH(callbacks, l, bus->filter_callbacks) {
1788 if (bus->filter_callbacks_modified)
1791 /* Don't run this more than once per iteration */
1792 if (l->last_iteration == bus->iteration_counter)
1795 l->last_iteration = bus->iteration_counter;
1797 r = sd_bus_message_rewind(m, true);
1801 r = l->callback(bus, m, l->userdata);
1807 } while (bus->filter_callbacks_modified);
1812 static int process_match(sd_bus *bus, sd_bus_message *m) {
1819 bus->match_callbacks_modified = false;
1821 r = bus_match_run(bus, &bus->match_callbacks, m);
1825 } while (bus->match_callbacks_modified);
1830 static int process_builtin(sd_bus *bus, sd_bus_message *m) {
1831 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1837 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
1840 if (!streq_ptr(m->interface, "org.freedesktop.DBus.Peer"))
1843 if (m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
1846 if (streq_ptr(m->member, "Ping"))
1847 r = sd_bus_message_new_method_return(bus, m, &reply);
1848 else if (streq_ptr(m->member, "GetMachineId")) {
1852 r = sd_id128_get_machine(&id);
1856 r = sd_bus_message_new_method_return(bus, m, &reply);
1860 r = sd_bus_message_append(reply, "s", sd_id128_to_string(id, sid));
1862 r = sd_bus_message_new_method_errorf(
1864 "org.freedesktop.DBus.Error.UnknownMethod",
1865 "Unknown method '%s' on interface '%s'.", m->member, m->interface);
1871 r = sd_bus_send(bus, reply, NULL);
1878 static int node_vtable_get_userdata(
1881 struct node_vtable *c,
1894 r = c->find(bus, path, c->interface, &u, u);
1903 static void *vtable_property_convert_userdata(const sd_bus_vtable *p, void *u) {
1906 return (uint8_t*) u + p->property.offset;
1909 static int vtable_property_get_userdata(
1912 struct vtable_member *p,
1923 r = node_vtable_get_userdata(bus, path, p->parent, &u);
1927 *userdata = vtable_property_convert_userdata(p->vtable, u);
1931 static int add_enumerated_to_set(sd_bus *bus, const char *prefix, struct node_enumerator *first, Set *s) {
1932 struct node_enumerator *c;
1939 LIST_FOREACH(enumerators, c, first) {
1940 char **children = NULL, **k;
1942 r = c->callback(bus, prefix, &children, c->userdata);
1946 STRV_FOREACH(k, children) {
1952 if (!object_path_is_valid(*k) && object_path_startswith(*k, prefix)) {
1958 r = set_consume(s, *k);
1969 static int add_subtree_to_set(sd_bus *bus, const char *prefix, struct node *n, Set *s) {
1978 r = add_enumerated_to_set(bus, prefix, n->enumerators, s);
1982 LIST_FOREACH(siblings, i, n->child) {
1985 t = strdup(i->path);
1989 r = set_consume(s, t);
1990 if (r < 0 && r != -EEXIST)
1993 r = add_subtree_to_set(bus, prefix, i, s);
2001 static int get_child_nodes(sd_bus *bus, const char *prefix, struct node *n, Set **_s) {
2009 s = set_new(string_hash_func, string_compare_func);
2013 r = add_subtree_to_set(bus, prefix, n, s);
2023 static int node_callbacks_run(
2026 struct node_callback *first,
2027 bool require_fallback,
2028 bool *found_object) {
2030 struct node_callback *c;
2035 assert(found_object);
2037 LIST_FOREACH(callbacks, c, first) {
2038 if (require_fallback && !c->is_fallback)
2041 *found_object = true;
2043 if (c->last_iteration == bus->iteration_counter)
2046 r = sd_bus_message_rewind(m, true);
2050 r = c->callback(bus, m, c->userdata);
2058 static int method_callbacks_run(
2061 struct vtable_member *c,
2062 bool require_fallback,
2063 bool *found_object) {
2065 const char *signature;
2072 assert(found_object);
2074 if (require_fallback && !c->parent->is_fallback)
2077 r = node_vtable_get_userdata(bus, m->path, c->parent, &u);
2081 *found_object = true;
2083 r = sd_bus_message_rewind(m, true);
2087 r = sd_bus_message_get_signature(m, true, &signature);
2091 if (!streq(c->vtable->method.signature, signature)) {
2092 r = sd_bus_reply_method_errorf(bus, m,
2093 "org.freedesktop.DBus.Error.InvalidArgs",
2094 "Invalid arguments '%s' to call %s:%s, expecting '%s'.",
2095 signature, c->interface, c->member, c->vtable->method.signature);
2102 return c->vtable->method.handler(bus, m, u);
2105 static int property_get_set_callbacks_run(
2108 struct vtable_member *c,
2109 bool require_fallback,
2111 bool *found_object) {
2113 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2114 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2120 assert(found_object);
2122 if (require_fallback && !c->parent->is_fallback)
2125 r = vtable_property_get_userdata(bus, m->path, c, &u);
2129 *found_object = true;
2131 r = sd_bus_message_new_method_return(bus, m, &reply);
2135 c->last_iteration = bus->iteration_counter;
2138 r = sd_bus_message_open_container(reply, 'v', c->vtable->property.signature);
2142 if (c->vtable->property.get) {
2143 r = c->vtable->property.get(bus, m->path, c->interface, c->member, reply, &error, u);
2147 assert_not_reached("automatic properties not supported yet");
2149 if (sd_bus_error_is_set(&error)) {
2150 r = sd_bus_reply_method_error(bus, m, &error);
2157 r = sd_bus_message_close_container(reply);
2162 if (c->vtable->type != _SD_BUS_VTABLE_WRITABLE_PROPERTY)
2163 sd_bus_error_setf(&error, "org.freedesktop.DBus.Error.PropertyReadOnly", "Property '%s' is not writable.", c->member);
2165 r = sd_bus_message_enter_container(m, 'v', c->vtable->property.signature);
2169 if (c->vtable->property.set) {
2170 r = c->vtable->property.set(bus, m->path, c->interface, c->member, m, &error, u);
2174 assert_not_reached("automatic properties not supported yet");
2177 if (sd_bus_error_is_set(&error)) {
2178 r = sd_bus_reply_method_error(bus, m, &error);
2185 r = sd_bus_message_exit_container(m);
2190 r = sd_bus_send(bus, reply, NULL);
2197 static int vtable_append_all_properties(
2199 sd_bus_message *reply,
2201 struct node_vtable *c,
2203 sd_bus_error *error) {
2205 const sd_bus_vtable *v;
2212 for (v = c->vtable+1; v->type != _SD_BUS_VTABLE_END; v++) {
2213 if (v->type != _SD_BUS_VTABLE_PROPERTY && v->type != _SD_BUS_VTABLE_WRITABLE_PROPERTY)
2216 r = sd_bus_message_open_container(reply, 'e', "sv");
2220 r = sd_bus_message_append(reply, "s", c->interface);
2224 r = sd_bus_message_open_container(reply, 'v', v->property.signature);
2228 r = v->property.get(bus, path, c->interface, v->property.member, reply, error, vtable_property_convert_userdata(v, userdata));
2232 if (sd_bus_error_is_set(error))
2235 r = sd_bus_message_close_container(reply);
2239 r = sd_bus_message_close_container(reply);
2247 static int property_get_all_callbacks_run(
2250 struct node_vtable *first,
2251 bool require_fallback,
2253 bool *found_object) {
2255 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2256 struct node_vtable *c;
2257 bool found_interface = false;
2262 assert(found_object);
2264 r = sd_bus_message_new_method_return(bus, m, &reply);
2268 r = sd_bus_message_open_container(reply, 'a', "{sv}");
2272 LIST_FOREACH(vtables, c, first) {
2273 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2276 if (require_fallback && !c->is_fallback)
2279 r = node_vtable_get_userdata(bus, m->path, c, &u);
2285 *found_object = true;
2287 if (iface && !streq(c->interface, iface))
2289 found_interface = true;
2291 c->last_iteration = bus->iteration_counter;
2293 r = vtable_append_all_properties(bus, reply, m->path, c, u, &error);
2297 if (sd_bus_error_is_set(&error)) {
2298 r = sd_bus_reply_method_error(bus, m, &error);
2306 if (!found_interface) {
2307 r = sd_bus_reply_method_errorf(
2309 "org.freedesktop.DBus.Error.UnknownInterface",
2310 "Unknown interface '%s'.", iface);
2317 r = sd_bus_message_close_container(reply);
2321 r = sd_bus_send(bus, reply, NULL);
2328 static bool bus_node_with_object_manager(sd_bus *bus, struct node *n) {
2331 if (n->object_manager)
2335 return bus_node_with_object_manager(bus, n->parent);
2340 static bool bus_node_exists(sd_bus *bus, struct node *n, const char *path, bool require_fallback) {
2341 struct node_vtable *c;
2342 struct node_callback *k;
2350 LIST_FOREACH(callbacks, k, n->callbacks) {
2351 if (require_fallback && !k->is_fallback)
2357 LIST_FOREACH(vtables, c, n->vtables) {
2359 if (require_fallback && !c->is_fallback)
2365 return !require_fallback && (n->enumerators || n->object_manager);
2369 static int process_introspect(
2373 bool require_fallback,
2374 bool *found_object) {
2376 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2377 _cleanup_set_free_free_ Set *s = NULL;
2378 struct introspect intro;
2379 struct node_vtable *c;
2386 assert(found_object);
2388 r = get_child_nodes(bus, m->path, n, &s);
2392 r = introspect_begin(&intro);
2396 r = introspect_write_default_interfaces(&intro, bus_node_with_object_manager(bus, n));
2400 empty = set_isempty(s);
2402 LIST_FOREACH(vtables, c, n->vtables) {
2405 if (require_fallback && !c->is_fallback)
2408 r = node_vtable_get_userdata(bus, m->path, c, &u);
2416 r = introspect_write_interface(&intro, c->interface, c->vtable);
2422 /* Nothing?, let's see if we exist at all, and if not
2423 * refuse to do anything */
2424 r = bus_node_exists(bus, n, m->path, require_fallback);
2432 *found_object = true;
2434 r = introspect_write_child_nodes(&intro, s, m->path);
2438 r = introspect_finish(&intro, bus, m, &reply);
2442 r = sd_bus_send(bus, reply, NULL);
2449 introspect_free(&intro);
2453 static int object_manager_serialize_vtable(
2455 sd_bus_message *reply,
2457 struct node_vtable *c,
2458 sd_bus_error *error) {
2469 r = node_vtable_get_userdata(bus, path, c, &u);
2473 r = sd_bus_message_open_container(reply, 'e', "sa{sv}");
2477 r = sd_bus_message_append(reply, "s", c->interface);
2481 r = sd_bus_message_open_container(reply, 'a', "{sv}");
2485 r = vtable_append_all_properties(bus, reply, path, c, u, error);
2489 r = sd_bus_message_close_container(reply);
2493 r = sd_bus_message_close_container(reply);
2500 static int object_manager_serialize_path(
2502 sd_bus_message *reply,
2504 bool require_fallback,
2505 sd_bus_error *error) {
2507 struct node_vtable *i;
2516 n = hashmap_get(bus->nodes, path);
2520 r = sd_bus_message_open_container(reply, 'e', "oa{sa{sv}}");
2524 r = sd_bus_message_append(reply, "o", path);
2528 r = sd_bus_message_open_container(reply, 'a', "{sa{sv}}");
2532 LIST_FOREACH(vtables, i, n->vtables) {
2534 if (require_fallback && !i->is_fallback)
2537 r = object_manager_serialize_vtable(bus, reply, path, i, error);
2540 if (sd_bus_error_is_set(error))
2544 r = sd_bus_message_close_container(reply);
2548 r = sd_bus_message_close_container(reply);
2555 static int object_manager_serialize_path_and_fallbacks(
2557 sd_bus_message *reply,
2559 sd_bus_error *error) {
2569 /* First, add all vtables registered for this path */
2570 r = object_manager_serialize_path(bus, reply, path, false, error);
2573 if (sd_bus_error_is_set(error))
2576 /* Second, add fallback vtables registered for any of the prefixes */
2585 e = strrchr(p, '/');
2591 r = object_manager_serialize_path(bus, reply, p, true, error);
2595 if (sd_bus_error_is_set(error))
2603 static int process_get_managed_objects(
2607 bool require_fallback,
2608 bool *found_object) {
2610 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2611 _cleanup_set_free_free_ Set *s = NULL;
2618 assert(found_object);
2620 if (!bus_node_with_object_manager(bus, n))
2623 r = get_child_nodes(bus, m->path, n, &s);
2627 r = sd_bus_message_new_method_return(bus, m, &reply);
2631 r = sd_bus_message_open_container(reply, 'a', "{oa{sa{sv}}}");
2635 empty = set_isempty(s);
2637 struct node_vtable *c;
2639 /* Hmm, so we have no children? Then let's check
2640 * whether we exist at all, i.e. whether at least one
2643 LIST_FOREACH(vtables, c, n->vtables) {
2645 if (require_fallback && !c->is_fallback)
2663 SET_FOREACH(path, s, i) {
2664 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2666 r = object_manager_serialize_path_and_fallbacks(bus, reply, path, &error);
2670 if (sd_bus_error_is_set(&error)) {
2671 r = sd_bus_reply_method_error(bus, m, &error);
2680 r = sd_bus_message_close_container(reply);
2684 r = sd_bus_send(bus, reply, NULL);
2691 static int object_find_and_run(sd_bus *bus, sd_bus_message *m, const char *p, bool require_fallback, bool *found_object) {
2693 struct vtable_member vtable_key, *v;
2699 assert(found_object);
2701 n = hashmap_get(bus->nodes, p);
2705 /* First, try object callbacks */
2706 r = node_callbacks_run(bus, m, n->callbacks, require_fallback, found_object);
2710 if (!m->interface || !m->member)
2713 /* Then, look for a known method */
2714 vtable_key.path = (char*) p;
2715 vtable_key.interface = m->interface;
2716 vtable_key.member = m->member;
2718 v = hashmap_get(bus->vtable_methods, &vtable_key);
2720 r = method_callbacks_run(bus, m, v, require_fallback, found_object);
2725 /* Then, look for a known property */
2726 if (streq(m->interface, "org.freedesktop.DBus.Properties")) {
2729 get = streq(m->member, "Get");
2731 if (get || streq(m->member, "Set")) {
2733 r = sd_bus_message_rewind(m, true);
2737 vtable_key.path = (char*) p;
2739 r = sd_bus_message_read(m, "ss", &vtable_key.interface, &vtable_key.member);
2743 v = hashmap_get(bus->vtable_properties, &vtable_key);
2745 r = property_get_set_callbacks_run(bus, m, v, require_fallback, get, found_object);
2750 } else if (streq(m->member, "GetAll")) {
2753 r = sd_bus_message_rewind(m, true);
2757 r = sd_bus_message_read(m, "s", &iface);
2764 r = property_get_all_callbacks_run(bus, m, n->vtables, require_fallback, iface, found_object);
2769 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
2771 r = process_introspect(bus, m, n, require_fallback, found_object);
2775 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.ObjectManager", "GetManagedObjects")) {
2777 r = process_get_managed_objects(bus, m, n, require_fallback, found_object);
2782 if (!*found_object) {
2783 r = bus_node_exists(bus, n, m->path, require_fallback);
2788 *found_object = true;
2794 static int process_object(sd_bus *bus, sd_bus_message *m) {
2797 bool found_object = false;
2802 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
2808 if (hashmap_isempty(bus->nodes))
2811 pl = strlen(m->path);
2815 bus->nodes_modified = false;
2817 r = object_find_and_run(bus, m, m->path, false, &found_object);
2821 /* Look for fallback prefixes */
2829 if (bus->nodes_modified)
2832 e = strrchr(p, '/');
2839 r = object_find_and_run(bus, m, p, true, &found_object);
2844 } while (bus->nodes_modified);
2849 if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "Get") ||
2850 sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "Set"))
2851 r = sd_bus_reply_method_errorf(
2853 "org.freedesktop.DBus.Error.UnknownProperty",
2854 "Unknown property or interface.");
2856 r = sd_bus_reply_method_errorf(
2858 "org.freedesktop.DBus.Error.UnknownMethod",
2859 "Unknown method '%s' or interface '%s'.", m->member, m->interface);
2867 static int process_message(sd_bus *bus, sd_bus_message *m) {
2873 bus->iteration_counter++;
2875 r = process_hello(bus, m);
2879 r = process_reply(bus, m);
2883 r = process_filter(bus, m);
2887 r = process_match(bus, m);
2891 r = process_builtin(bus, m);
2895 return process_object(bus, m);
2898 static int process_running(sd_bus *bus, sd_bus_message **ret) {
2899 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2903 assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
2905 r = process_timeout(bus);
2909 r = dispatch_wqueue(bus);
2913 r = dispatch_rqueue(bus, &m);
2919 r = process_message(bus, m);
2924 r = sd_bus_message_rewind(m, true);
2933 if (m->header->type == SD_BUS_MESSAGE_TYPE_METHOD_CALL) {
2935 r = sd_bus_reply_method_errorf(
2937 "org.freedesktop.DBus.Error.UnknownObject",
2938 "Unknown object '%s'.", m->path);
2952 int sd_bus_process(sd_bus *bus, sd_bus_message **ret) {
2955 /* Returns 0 when we didn't do anything. This should cause the
2956 * caller to invoke sd_bus_wait() before returning the next
2957 * time. Returns > 0 when we did something, which possibly
2958 * means *ret is filled in with an unprocessed message. */
2962 if (bus_pid_changed(bus))
2965 /* We don't allow recursively invoking sd_bus_process(). */
2966 if (bus->processing)
2969 switch (bus->state) {
2976 r = bus_socket_process_opening(bus);
2983 case BUS_AUTHENTICATING:
2985 r = bus_socket_process_authenticating(bus);
2995 bus->processing = true;
2996 r = process_running(bus, ret);
2997 bus->processing = false;
3002 assert_not_reached("Unknown state");
3005 static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec) {
3006 struct pollfd p[2] = {};
3013 if (!BUS_IS_OPEN(bus->state))
3016 e = sd_bus_get_events(bus);
3023 r = sd_bus_get_timeout(bus, &until);
3030 nw = now(CLOCK_MONOTONIC);
3031 m = until > nw ? until - nw : 0;
3034 if (timeout_usec != (uint64_t) -1 && (m == (uint64_t) -1 || timeout_usec < m))
3037 p[0].fd = bus->input_fd;
3038 if (bus->output_fd == bus->input_fd) {
3042 p[0].events = e & POLLIN;
3043 p[1].fd = bus->output_fd;
3044 p[1].events = e & POLLOUT;
3048 r = ppoll(p, n, m == (uint64_t) -1 ? NULL : timespec_store(&ts, m), NULL);
3052 return r > 0 ? 1 : 0;
3055 int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec) {
3059 if (!BUS_IS_OPEN(bus->state))
3061 if (bus_pid_changed(bus))
3064 if (bus->rqueue_size > 0)
3067 return bus_poll(bus, false, timeout_usec);
3070 int sd_bus_flush(sd_bus *bus) {
3075 if (!BUS_IS_OPEN(bus->state))
3077 if (bus_pid_changed(bus))
3080 r = bus_ensure_running(bus);
3084 if (bus->wqueue_size <= 0)
3088 r = dispatch_wqueue(bus);
3092 if (bus->wqueue_size <= 0)
3095 r = bus_poll(bus, false, (uint64_t) -1);
3101 int sd_bus_add_filter(sd_bus *bus, sd_bus_message_handler_t callback, void *userdata) {
3102 struct filter_callback *f;
3108 if (bus_pid_changed(bus))
3111 f = new0(struct filter_callback, 1);
3114 f->callback = callback;
3115 f->userdata = userdata;
3117 bus->filter_callbacks_modified = true;
3118 LIST_PREPEND(struct filter_callback, callbacks, bus->filter_callbacks, f);
3122 int sd_bus_remove_filter(sd_bus *bus, sd_bus_message_handler_t callback, void *userdata) {
3123 struct filter_callback *f;
3129 if (bus_pid_changed(bus))
3132 LIST_FOREACH(callbacks, f, bus->filter_callbacks) {
3133 if (f->callback == callback && f->userdata == userdata) {
3134 bus->filter_callbacks_modified = true;
3135 LIST_REMOVE(struct filter_callback, callbacks, bus->filter_callbacks, f);
3144 static struct node *bus_node_allocate(sd_bus *bus, const char *path) {
3145 struct node *n, *parent;
3152 assert(path[0] == '/');
3154 n = hashmap_get(bus->nodes, path);
3158 r = hashmap_ensure_allocated(&bus->nodes, string_hash_func, string_compare_func);
3166 if (streq(path, "/"))
3169 e = strrchr(path, '/');
3172 p = strndupa(path, MAX(1, path - e));
3174 parent = bus_node_allocate(bus, p);
3181 n = new0(struct node, 1);
3188 r = hashmap_put(bus->nodes, s, n);
3196 LIST_PREPEND(struct node, siblings, parent->child, n);
3201 static void bus_node_gc(sd_bus *b, struct node *n) {
3214 assert(hashmap_remove(b->nodes, n->path) == n);
3217 LIST_REMOVE(struct node, siblings, n->parent->child, n);
3220 bus_node_gc(b, n->parent);
3224 static int bus_add_object(
3228 sd_bus_message_handler_t callback,
3231 struct node_callback *c;
3237 if (!object_path_is_valid(path))
3241 if (bus_pid_changed(b))
3244 n = bus_node_allocate(b, path);
3248 c = new0(struct node_callback, 1);
3255 c->callback = callback;
3256 c->userdata = userdata;
3257 c->is_fallback = fallback;
3259 LIST_PREPEND(struct node_callback, callbacks, n->callbacks, c);
3268 static int bus_remove_object(
3272 sd_bus_message_handler_t callback,
3275 struct node_callback *c;
3280 if (!object_path_is_valid(path))
3284 if (bus_pid_changed(bus))
3287 n = hashmap_get(bus->nodes, path);
3291 LIST_FOREACH(callbacks, c, n->callbacks)
3292 if (c->callback == callback && c->userdata == userdata && c->is_fallback == fallback)
3297 LIST_REMOVE(struct node_callback, callbacks, n->callbacks, c);
3300 bus_node_gc(bus, n);
3305 int sd_bus_add_object(sd_bus *bus, const char *path, sd_bus_message_handler_t callback, void *userdata) {
3306 return bus_add_object(bus, false, path, callback, userdata);
3309 int sd_bus_remove_object(sd_bus *bus, const char *path, sd_bus_message_handler_t callback, void *userdata) {
3310 return bus_remove_object(bus, false, path, callback, userdata);
3313 int sd_bus_add_fallback(sd_bus *bus, const char *prefix, sd_bus_message_handler_t callback, void *userdata) {
3314 return bus_add_object(bus, true, prefix, callback, userdata);
3317 int sd_bus_remove_fallback(sd_bus *bus, const char *prefix, sd_bus_message_handler_t callback, void *userdata) {
3318 return bus_remove_object(bus, true, prefix, callback, userdata);
3321 int sd_bus_add_match(sd_bus *bus, const char *match, sd_bus_message_handler_t callback, void *userdata) {
3322 struct bus_match_component *components = NULL;
3323 unsigned n_components = 0;
3324 uint64_t cookie = 0;
3331 if (bus_pid_changed(bus))
3334 r = bus_match_parse(match, &components, &n_components);
3338 if (bus->bus_client) {
3339 cookie = ++bus->match_cookie;
3341 r = bus_add_match_internal(bus, match, components, n_components, cookie);
3346 bus->match_callbacks_modified = true;
3347 r = bus_match_add(&bus->match_callbacks, components, n_components, callback, userdata, cookie, NULL);
3349 if (bus->bus_client)
3350 bus_remove_match_internal(bus, match, cookie);
3354 bus_match_parse_free(components, n_components);
3358 int sd_bus_remove_match(sd_bus *bus, const char *match, sd_bus_message_handler_t callback, void *userdata) {
3359 struct bus_match_component *components = NULL;
3360 unsigned n_components = 0;
3362 uint64_t cookie = 0;
3368 if (bus_pid_changed(bus))
3371 r = bus_match_parse(match, &components, &n_components);
3375 bus->match_callbacks_modified = true;
3376 r = bus_match_remove(&bus->match_callbacks, components, n_components, callback, userdata, &cookie);
3378 if (bus->bus_client)
3379 q = bus_remove_match_internal(bus, match, cookie);
3381 bus_match_parse_free(components, n_components);
3383 return r < 0 ? r : q;
3386 int sd_bus_emit_signal(
3389 const char *interface,
3391 const char *types, ...) {
3393 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
3399 if (!BUS_IS_OPEN(bus->state))
3401 if (bus_pid_changed(bus))
3404 r = sd_bus_message_new_signal(bus, path, interface, member, &m);
3408 va_start(ap, types);
3409 r = bus_message_append_ap(m, types, ap);
3414 return sd_bus_send(bus, m, NULL);
3417 int sd_bus_call_method(
3419 const char *destination,
3421 const char *interface,
3423 sd_bus_error *error,
3424 sd_bus_message **reply,
3425 const char *types, ...) {
3427 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
3434 if (!BUS_IS_OPEN(bus->state))
3436 if (bus_pid_changed(bus))
3439 r = sd_bus_message_new_method_call(bus, destination, path, interface, member, &m);
3443 va_start(ap, types);
3444 r = bus_message_append_ap(m, types, ap);
3449 return sd_bus_send_with_reply_and_block(bus, m, 0, error, reply);
3452 int sd_bus_reply_method_return(
3454 sd_bus_message *call,
3455 const char *types, ...) {
3457 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
3467 if (call->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
3469 if (!BUS_IS_OPEN(bus->state))
3471 if (bus_pid_changed(bus))
3474 if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
3477 r = sd_bus_message_new_method_return(bus, call, &m);
3481 va_start(ap, types);
3482 r = bus_message_append_ap(m, types, ap);
3487 return sd_bus_send(bus, m, NULL);
3490 int sd_bus_reply_method_error(
3492 sd_bus_message *call,
3493 const sd_bus_error *e) {
3495 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
3504 if (call->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
3506 if (!sd_bus_error_is_set(e))
3508 if (!BUS_IS_OPEN(bus->state))
3510 if (bus_pid_changed(bus))
3513 if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
3516 r = sd_bus_message_new_method_error(bus, call, e, &m);
3520 return sd_bus_send(bus, m, NULL);
3523 int sd_bus_reply_method_errorf(
3525 sd_bus_message *call,
3530 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3540 va_start(ap, format);
3541 r = vasprintf(&m, format, ap);
3552 error.need_free = true;
3554 return sd_bus_reply_method_error(bus, call, &error);
3557 bool bus_pid_changed(sd_bus *bus) {
3560 /* We don't support people creating a bus connection and
3561 * keeping it around over a fork(). Let's complain. */
3563 return bus->original_pid != getpid();
3566 static void free_node_vtable(sd_bus *bus, struct node_vtable *w) {
3572 if (w->interface && w->node && w->vtable) {
3573 const sd_bus_vtable *v;
3575 for (v = w->vtable; v->type != _SD_BUS_VTABLE_END; w++) {
3576 struct vtable_member *x = NULL;
3580 case _SD_BUS_VTABLE_METHOD: {
3581 struct vtable_member key;
3583 key.path = w->node->path;
3584 key.interface = w->interface;
3585 key.member = v->method.member;
3587 x = hashmap_remove(bus->vtable_methods, &key);
3591 case _SD_BUS_VTABLE_PROPERTY:
3592 case _SD_BUS_VTABLE_WRITABLE_PROPERTY: {
3593 struct vtable_member key;
3595 key.path = w->node->path;
3596 key.interface = w->interface;
3597 key.member = v->property.member;
3598 x = hashmap_remove(bus->vtable_properties, &key);
3610 static unsigned vtable_member_hash_func(const void *a) {
3611 const struct vtable_member *m = a;
3614 string_hash_func(m->path) ^
3615 string_hash_func(m->interface) ^
3616 string_hash_func(m->member);
3619 static int vtable_member_compare_func(const void *a, const void *b) {
3620 const struct vtable_member *x = a, *y = b;
3623 r = strcmp(x->path, y->path);
3627 r = strcmp(x->interface, y->interface);
3631 return strcmp(x->member, y->member);
3634 static int add_object_vtable_internal(
3637 const char *interface,
3638 const sd_bus_vtable *vtable,
3640 sd_bus_object_find_t find,
3643 struct node_vtable *c, *i;
3644 const sd_bus_vtable *v;
3650 if (!object_path_is_valid(path))
3652 if (!interface_name_is_valid(interface))
3654 if (!vtable || vtable[0].type != _SD_BUS_VTABLE_START || vtable[0].start.element_size != sizeof(struct sd_bus_vtable))
3656 if (bus_pid_changed(bus))
3659 r = hashmap_ensure_allocated(&bus->vtable_methods, vtable_member_hash_func, vtable_member_compare_func);
3663 r = hashmap_ensure_allocated(&bus->vtable_properties, vtable_member_hash_func, vtable_member_compare_func);
3667 n = bus_node_allocate(bus, path);
3671 LIST_FOREACH(vtables, i, n->vtables) {
3672 if (streq(i->interface, interface)) {
3677 if (i->is_fallback != fallback) {
3683 c = new0(struct node_vtable, 1);
3690 c->is_fallback = fallback;
3692 c->userdata = userdata;
3695 c->interface = strdup(interface);
3696 if (!c->interface) {
3701 for (v = c->vtable+1; v->type != _SD_BUS_VTABLE_END; v++) {
3705 case _SD_BUS_VTABLE_METHOD: {
3706 struct vtable_member *m;
3708 if (!member_name_is_valid(v->method.member) ||
3709 !signature_is_valid(v->method.signature, false) ||
3710 !signature_is_valid(v->method.result, false) ||
3711 !v->method.handler ||
3712 v->flags & (SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE|SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY)) {
3717 m = new0(struct vtable_member, 1);
3725 m->interface = c->interface;
3726 m->member = v->method.member;
3729 r = hashmap_put(bus->vtable_methods, m, m);
3738 case _SD_BUS_VTABLE_PROPERTY:
3739 case _SD_BUS_VTABLE_WRITABLE_PROPERTY: {
3740 struct vtable_member *m;
3742 if (!member_name_is_valid(v->property.member) ||
3743 !signature_is_single(v->property.signature, false) ||
3744 v->flags & SD_BUS_VTABLE_METHOD_NO_REPLY ||
3745 (v->flags & SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY && !(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE))) {
3751 m = new0(struct vtable_member, 1);
3759 m->interface = c->interface;
3760 m->member = v->property.member;
3763 r = hashmap_put(bus->vtable_properties, m, m);
3772 case _SD_BUS_VTABLE_SIGNAL:
3774 if (!member_name_is_valid(v->signal.member) ||
3775 !signature_is_single(v->signal.signature, false)) {
3788 LIST_PREPEND(struct node_vtable, vtables, n->vtables, c);
3793 free_node_vtable(bus, c);
3795 bus_node_gc(bus, n);
3799 static int remove_object_vtable_internal(
3802 const char *interface,
3805 struct node_vtable *c;
3810 if (!object_path_is_valid(path))
3812 if (!interface_name_is_valid(interface))
3814 if (bus_pid_changed(bus))
3817 n = hashmap_get(bus->nodes, path);
3821 LIST_FOREACH(vtables, c, n->vtables)
3822 if (streq(c->interface, interface) && c->is_fallback == fallback)
3828 LIST_REMOVE(struct node_vtable, vtables, n->vtables, c);
3830 free_node_vtable(bus, c);
3834 int sd_bus_add_object_vtable(
3837 const char *interface,
3838 const sd_bus_vtable *vtable,
3841 return add_object_vtable_internal(bus, path, interface, vtable, false, NULL, userdata);
3844 int sd_bus_remove_object_vtable(
3847 const char *interface) {
3849 return remove_object_vtable_internal(bus, path, interface, false);
3852 int sd_bus_add_fallback_vtable(
3855 const char *interface,
3856 const sd_bus_vtable *vtable,
3857 sd_bus_object_find_t find,
3860 return add_object_vtable_internal(bus, path, interface, vtable, true, find, userdata);
3863 int sd_bus_remove_fallback_vtable(
3866 const char *interface) {
3868 return remove_object_vtable_internal(bus, path, interface, true);
3871 int sd_bus_add_node_enumerator(
3874 sd_bus_node_enumerator_t callback,
3877 struct node_enumerator *c;
3883 if (!object_path_is_valid(path))
3887 if (bus_pid_changed(bus))
3890 n = bus_node_allocate(bus, path);
3894 c = new0(struct node_enumerator, 1);
3901 c->callback = callback;
3902 c->userdata = userdata;
3904 LIST_PREPEND(struct node_enumerator, enumerators, n->enumerators, c);
3909 bus_node_gc(bus, n);
3913 int sd_bus_remove_node_enumerator(
3916 sd_bus_node_enumerator_t callback,
3919 struct node_enumerator *c;
3924 if (!object_path_is_valid(path))
3928 if (bus_pid_changed(bus))
3931 n = hashmap_get(bus->nodes, path);
3935 LIST_FOREACH(enumerators, c, n->enumerators)
3936 if (c->callback == callback && c->userdata == userdata)
3942 LIST_REMOVE(struct node_enumerator, enumerators, n->enumerators, c);
3945 bus_node_gc(bus, n);
3950 static int emit_properties_changed_on_interface(
3954 const char *interface,
3955 bool require_fallback,
3958 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
3959 bool has_invalidating = false;
3960 struct vtable_member key;
3961 struct node_vtable *c;
3971 n = hashmap_get(bus->nodes, prefix);
3975 LIST_FOREACH(vtables, c, n->vtables) {
3976 if (require_fallback && !c->is_fallback)
3979 if (streq(c->interface, interface))
3982 r = node_vtable_get_userdata(bus, path, c, &u);
3992 r = sd_bus_message_new_signal(bus, path, "org.freedesktop.DBus", "PropertiesChanged", &m);
3996 r = sd_bus_message_append(m, "s", interface);
4000 r = sd_bus_message_open_container(m, 'a', "{sv}");
4005 key.interface = interface;
4007 STRV_FOREACH(property, names) {
4008 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4009 struct vtable_member *v;
4011 key.member = *property;
4012 v = hashmap_get(bus->vtable_properties, &key);
4016 assert(c == v->parent);
4018 if (!(v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE))
4020 if (v->vtable->flags & SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY) {
4021 has_invalidating = true;
4025 r = sd_bus_message_open_container(m, 'e', "sv");
4029 r = sd_bus_message_append(m, "s", *n);
4033 r = sd_bus_message_open_container(m, 'v', v->vtable->property.signature);
4037 r = v->vtable->property.get(bus, m->path, interface, *property, m, &error, u);
4041 if (sd_bus_error_is_set(&error))
4042 return bus_error_to_errno(&error);
4044 r = sd_bus_message_close_container(m);
4048 r = sd_bus_message_close_container(m);
4053 r = sd_bus_message_close_container(m);
4057 r = sd_bus_message_open_container(m, 'a', "s");
4061 if (has_invalidating) {
4062 STRV_FOREACH(property, names) {
4063 struct vtable_member *v;
4065 key.member = *property;
4066 assert_se(v = hashmap_get(bus->vtable_properties, &key));
4067 assert(c == v->parent);
4069 if (!(v->vtable->flags & SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY))
4072 r = sd_bus_message_append(m, "s", *property);
4078 r = sd_bus_message_close_container(m);
4082 r = sd_bus_send(bus, m, NULL);
4089 int sd_bus_emit_properties_changed_strv(sd_bus *bus, const char *path, const char *interface, char **names) {
4095 if (!object_path_is_valid(path))
4097 if (!interface_name_is_valid(interface))
4100 r = emit_properties_changed_on_interface(bus, path, path, interface, false, names);
4115 e = strrchr(p, '/');
4122 r = emit_properties_changed_on_interface(bus, p, path, interface, true, names);
4131 int sd_bus_emit_properties_changed(sd_bus *bus, const char *path, const char *interface, const char *name, ...) {
4132 _cleanup_strv_free_ char **names = NULL;
4136 names = strv_new_ap(name, ap);
4142 return sd_bus_emit_properties_changed_strv(bus, path, interface, names);
4145 int sd_bus_emit_interfaces_added(sd_bus *bus, const char *path, const char *interfaces, ...) {
4149 int sd_bus_emit_interfaces_removed(sd_bus *bus, const char *path, const char *interfaces, ...) {
4153 int sd_bus_get_property(
4155 const char *destination,
4157 const char *interface,
4159 sd_bus_error *error,
4160 sd_bus_message **reply,
4163 sd_bus_message *rep = NULL;
4166 if (interface && !interface_name_is_valid(interface))
4168 if (!member_name_is_valid(member))
4170 if (!signature_is_single(type, false))
4175 r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &rep, "ss", strempty(interface), member);
4179 r = sd_bus_message_enter_container(rep, 'v', type);
4181 sd_bus_message_unref(rep);
4189 int sd_bus_set_property(
4191 const char *destination,
4193 const char *interface,
4195 sd_bus_error *error,
4196 const char *type, ...) {
4198 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4202 if (interface && !interface_name_is_valid(interface))
4204 if (!member_name_is_valid(member))
4206 if (!signature_is_single(type, false))
4209 r = sd_bus_message_new_method_call(bus, destination, path, "org.freedesktop.DBus.Properties", "Set", &m);
4213 r = sd_bus_message_append(m, "ss", strempty(interface), member);
4217 r = sd_bus_message_open_container(m, 'v', type);
4222 r = bus_message_append_ap(m, type, ap);
4227 r = sd_bus_message_close_container(m);
4231 return sd_bus_send_with_reply_and_block(bus, m, 0, error, NULL);
4234 int sd_bus_add_object_manager(sd_bus *bus, const char *path) {
4239 if (!object_path_is_valid(path))
4241 if (bus_pid_changed(bus))
4244 n = bus_node_allocate(bus, path);
4248 n->object_manager = true;
4252 int sd_bus_remove_object_manager(sd_bus *bus, const char *path) {
4257 if (!object_path_is_valid(path))
4259 if (bus_pid_changed(bus))
4262 n = hashmap_get(bus->nodes, path);
4266 if (!n->object_manager)
4269 n->object_manager = false;
4270 bus_node_gc(bus, n);