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,
1893 r = c->find(bus, path, c->interface, &u, u);
1904 static void *vtable_property_convert_userdata(const sd_bus_vtable *p, void *u) {
1907 return (uint8_t*) u + p->property.offset;
1910 static int vtable_property_get_userdata(
1913 struct vtable_member *p,
1924 r = node_vtable_get_userdata(bus, path, p->parent, &u);
1928 *userdata = vtable_property_convert_userdata(p->vtable, u);
1932 static int add_enumerated_to_set(sd_bus *bus, const char *prefix, struct node_enumerator *first, Set *s) {
1933 struct node_enumerator *c;
1940 LIST_FOREACH(enumerators, c, first) {
1941 char **children = NULL, **k;
1943 r = c->callback(bus, prefix, &children, c->userdata);
1947 STRV_FOREACH(k, children) {
1953 if (!object_path_is_valid(*k) && object_path_startswith(*k, prefix)) {
1959 r = set_consume(s, *k);
1970 static int add_subtree_to_set(sd_bus *bus, const char *prefix, struct node *n, Set *s) {
1979 r = add_enumerated_to_set(bus, prefix, n->enumerators, s);
1983 LIST_FOREACH(siblings, i, n->child) {
1986 t = strdup(i->path);
1990 r = set_consume(s, t);
1991 if (r < 0 && r != -EEXIST)
1994 r = add_subtree_to_set(bus, prefix, i, s);
2002 static int get_child_nodes(sd_bus *bus, const char *prefix, struct node *n, Set **_s) {
2010 s = set_new(string_hash_func, string_compare_func);
2014 r = add_subtree_to_set(bus, prefix, n, s);
2024 static int node_callbacks_run(
2027 struct node_callback *first,
2028 bool require_fallback,
2029 bool *found_object) {
2031 struct node_callback *c;
2036 assert(found_object);
2038 LIST_FOREACH(callbacks, c, first) {
2039 if (require_fallback && !c->is_fallback)
2042 *found_object = true;
2044 if (c->last_iteration == bus->iteration_counter)
2047 r = sd_bus_message_rewind(m, true);
2051 r = c->callback(bus, m, c->userdata);
2059 static int method_callbacks_run(
2062 struct vtable_member *c,
2063 bool require_fallback,
2064 bool *found_object) {
2066 const char *signature;
2073 assert(found_object);
2075 if (require_fallback && !c->parent->is_fallback)
2078 r = node_vtable_get_userdata(bus, m->path, c->parent, &u);
2082 *found_object = true;
2084 r = sd_bus_message_rewind(m, true);
2088 r = sd_bus_message_get_signature(m, true, &signature);
2092 if (!streq(strempty(c->vtable->method.signature), signature)) {
2093 r = sd_bus_reply_method_errorf(bus, m,
2094 "org.freedesktop.DBus.Error.InvalidArgs",
2095 "Invalid arguments '%s' to call %s:%s, expecting '%s'.",
2096 signature, c->interface, c->member, strempty(c->vtable->method.signature));
2103 if (c->vtable->method.handler)
2104 return c->vtable->method.handler(bus, m, u);
2106 /* If the method callback is NULL, make this a successful NOP */
2107 r = sd_bus_reply_method_return(bus, m, NULL);
2114 static int invoke_property_get(
2116 const sd_bus_vtable *v,
2118 const char *interface,
2119 const char *property,
2121 sd_bus_error *error,
2130 if (v->property.get)
2131 return v->property.get(bus, path, interface, property, m, error, userdata);
2133 /* Automatic handling if no callback is defined. */
2135 assert(bus_type_is_basic(v->property.signature[0]));
2137 switch (v->property.signature[0]) {
2139 case SD_BUS_TYPE_STRING:
2140 case SD_BUS_TYPE_OBJECT_PATH:
2141 case SD_BUS_TYPE_SIGNATURE:
2142 p = *(char**) userdata;
2150 r = sd_bus_message_append_basic(m, v->property.signature[0], p);
2157 static int invoke_property_set(
2159 const sd_bus_vtable *v,
2161 const char *interface,
2162 const char *property,
2163 sd_bus_message *value,
2164 sd_bus_error *error,
2172 if (v->property.set)
2173 return v->property.set(bus, path, interface, property, value, error, userdata);
2175 /* Automatic handling if no callback is defined. */
2177 assert(signature_is_single(v->property.signature, false));
2178 assert(bus_type_is_basic(v->property.signature[0]));
2180 switch (v->property.signature[0]) {
2182 case SD_BUS_TYPE_STRING:
2183 case SD_BUS_TYPE_OBJECT_PATH:
2184 case SD_BUS_TYPE_SIGNATURE: {
2188 r = sd_bus_message_read_basic(value, v->property.signature[0], &p);
2196 free(*(char**) userdata);
2197 *(char**) userdata = n;
2203 r = sd_bus_message_read_basic(value, v->property.signature[0], userdata);
2213 static int property_get_set_callbacks_run(
2216 struct vtable_member *c,
2217 bool require_fallback,
2219 bool *found_object) {
2221 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2222 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2228 assert(found_object);
2230 if (require_fallback && !c->parent->is_fallback)
2233 r = vtable_property_get_userdata(bus, m->path, c, &u);
2237 *found_object = true;
2239 r = sd_bus_message_new_method_return(bus, m, &reply);
2243 c->last_iteration = bus->iteration_counter;
2246 r = sd_bus_message_open_container(reply, 'v', c->vtable->property.signature);
2250 r = invoke_property_get(bus, c->vtable, m->path, c->interface, c->member, reply, &error, u);
2254 if (sd_bus_error_is_set(&error)) {
2255 r = sd_bus_reply_method_error(bus, m, &error);
2262 r = sd_bus_message_close_container(reply);
2267 if (c->vtable->type != _SD_BUS_VTABLE_WRITABLE_PROPERTY)
2268 sd_bus_error_setf(&error, "org.freedesktop.DBus.Error.PropertyReadOnly", "Property '%s' is not writable.", c->member);
2270 r = sd_bus_message_enter_container(m, 'v', c->vtable->property.signature);
2274 r = invoke_property_set(bus, c->vtable, m->path, c->interface, c->member, m, &error, u);
2279 if (sd_bus_error_is_set(&error)) {
2280 r = sd_bus_reply_method_error(bus, m, &error);
2287 r = sd_bus_message_exit_container(m);
2292 r = sd_bus_send(bus, reply, NULL);
2299 static int vtable_append_all_properties(
2301 sd_bus_message *reply,
2303 struct node_vtable *c,
2305 sd_bus_error *error) {
2307 const sd_bus_vtable *v;
2314 for (v = c->vtable+1; v->type != _SD_BUS_VTABLE_END; v++) {
2315 if (v->type != _SD_BUS_VTABLE_PROPERTY && v->type != _SD_BUS_VTABLE_WRITABLE_PROPERTY)
2318 r = sd_bus_message_open_container(reply, 'e', "sv");
2322 r = sd_bus_message_append(reply, "s", c->interface);
2326 r = sd_bus_message_open_container(reply, 'v', v->property.signature);
2330 r = invoke_property_get(bus, v, path, c->interface, v->property.member, reply, error, vtable_property_convert_userdata(v, userdata));
2334 if (sd_bus_error_is_set(error))
2337 r = sd_bus_message_close_container(reply);
2341 r = sd_bus_message_close_container(reply);
2349 static int property_get_all_callbacks_run(
2352 struct node_vtable *first,
2353 bool require_fallback,
2355 bool *found_object) {
2357 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2358 struct node_vtable *c;
2359 bool found_interface = false;
2364 assert(found_object);
2366 r = sd_bus_message_new_method_return(bus, m, &reply);
2370 r = sd_bus_message_open_container(reply, 'a', "{sv}");
2374 LIST_FOREACH(vtables, c, first) {
2375 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2378 if (require_fallback && !c->is_fallback)
2381 r = node_vtable_get_userdata(bus, m->path, c, &u);
2387 *found_object = true;
2389 if (iface && !streq(c->interface, iface))
2391 found_interface = true;
2393 c->last_iteration = bus->iteration_counter;
2395 r = vtable_append_all_properties(bus, reply, m->path, c, u, &error);
2399 if (sd_bus_error_is_set(&error)) {
2400 r = sd_bus_reply_method_error(bus, m, &error);
2408 if (!found_interface) {
2409 r = sd_bus_reply_method_errorf(
2411 "org.freedesktop.DBus.Error.UnknownInterface",
2412 "Unknown interface '%s'.", iface);
2419 r = sd_bus_message_close_container(reply);
2423 r = sd_bus_send(bus, reply, NULL);
2430 static bool bus_node_with_object_manager(sd_bus *bus, struct node *n) {
2433 if (n->object_manager)
2437 return bus_node_with_object_manager(bus, n->parent);
2442 static bool bus_node_exists(sd_bus *bus, struct node *n, const char *path, bool require_fallback) {
2443 struct node_vtable *c;
2444 struct node_callback *k;
2449 /* Tests if there's anything attached directly to this node
2450 * for the specified path */
2452 LIST_FOREACH(callbacks, k, n->callbacks) {
2453 if (require_fallback && !k->is_fallback)
2459 LIST_FOREACH(vtables, c, n->vtables) {
2461 if (require_fallback && !c->is_fallback)
2464 if (node_vtable_get_userdata(bus, path, c, NULL) > 0)
2468 return !require_fallback && (n->enumerators || n->object_manager);
2471 static int process_introspect(
2475 bool require_fallback,
2476 bool *found_object) {
2478 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2479 _cleanup_set_free_free_ Set *s = NULL;
2480 struct introspect intro;
2481 struct node_vtable *c;
2488 assert(found_object);
2490 r = get_child_nodes(bus, m->path, n, &s);
2494 r = introspect_begin(&intro);
2498 r = introspect_write_default_interfaces(&intro, bus_node_with_object_manager(bus, n));
2502 empty = set_isempty(s);
2504 LIST_FOREACH(vtables, c, n->vtables) {
2505 if (require_fallback && !c->is_fallback)
2508 r = node_vtable_get_userdata(bus, m->path, c, NULL);
2516 r = introspect_write_interface(&intro, c->interface, c->vtable);
2522 /* Nothing?, let's see if we exist at all, and if not
2523 * refuse to do anything */
2524 r = bus_node_exists(bus, n, m->path, require_fallback);
2532 *found_object = true;
2534 r = introspect_write_child_nodes(&intro, s, m->path);
2538 r = introspect_finish(&intro, bus, m, &reply);
2542 r = sd_bus_send(bus, reply, NULL);
2549 introspect_free(&intro);
2553 static int object_manager_serialize_vtable(
2555 sd_bus_message *reply,
2557 struct node_vtable *c,
2558 sd_bus_error *error) {
2569 r = node_vtable_get_userdata(bus, path, c, &u);
2573 r = sd_bus_message_open_container(reply, 'e', "sa{sv}");
2577 r = sd_bus_message_append(reply, "s", c->interface);
2581 r = sd_bus_message_open_container(reply, 'a', "{sv}");
2585 r = vtable_append_all_properties(bus, reply, path, c, u, error);
2589 r = sd_bus_message_close_container(reply);
2593 r = sd_bus_message_close_container(reply);
2600 static int object_manager_serialize_path(
2602 sd_bus_message *reply,
2605 bool require_fallback,
2606 sd_bus_error *error) {
2608 struct node_vtable *i;
2618 n = hashmap_get(bus->nodes, prefix);
2622 r = sd_bus_message_open_container(reply, 'e', "oa{sa{sv}}");
2626 r = sd_bus_message_append(reply, "o", path);
2630 r = sd_bus_message_open_container(reply, 'a', "{sa{sv}}");
2634 LIST_FOREACH(vtables, i, n->vtables) {
2636 if (require_fallback && !i->is_fallback)
2639 r = object_manager_serialize_vtable(bus, reply, path, i, error);
2642 if (sd_bus_error_is_set(error))
2646 r = sd_bus_message_close_container(reply);
2650 r = sd_bus_message_close_container(reply);
2657 static int object_manager_serialize_path_and_fallbacks(
2659 sd_bus_message *reply,
2661 sd_bus_error *error) {
2671 /* First, add all vtables registered for this path */
2672 r = object_manager_serialize_path(bus, reply, path, path, false, error);
2675 if (sd_bus_error_is_set(error))
2678 /* Second, add fallback vtables registered for any of the prefixes */
2687 e = strrchr(p, '/');
2693 r = object_manager_serialize_path(bus, reply, p, path, true, error);
2697 if (sd_bus_error_is_set(error))
2705 static int process_get_managed_objects(
2709 bool require_fallback,
2710 bool *found_object) {
2712 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2713 _cleanup_set_free_free_ Set *s = NULL;
2720 assert(found_object);
2722 if (!bus_node_with_object_manager(bus, n))
2725 r = get_child_nodes(bus, m->path, n, &s);
2729 r = sd_bus_message_new_method_return(bus, m, &reply);
2733 r = sd_bus_message_open_container(reply, 'a', "{oa{sa{sv}}}");
2737 empty = set_isempty(s);
2739 struct node_vtable *c;
2741 /* Hmm, so we have no children? Then let's check
2742 * whether we exist at all, i.e. whether at least one
2745 LIST_FOREACH(vtables, c, n->vtables) {
2747 if (require_fallback && !c->is_fallback)
2765 SET_FOREACH(path, s, i) {
2766 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2768 r = object_manager_serialize_path_and_fallbacks(bus, reply, path, &error);
2772 if (sd_bus_error_is_set(&error)) {
2773 r = sd_bus_reply_method_error(bus, m, &error);
2782 r = sd_bus_message_close_container(reply);
2786 r = sd_bus_send(bus, reply, NULL);
2793 static int object_find_and_run(
2797 bool require_fallback,
2798 bool *found_object) {
2801 struct vtable_member vtable_key, *v;
2807 assert(found_object);
2809 n = hashmap_get(bus->nodes, p);
2813 /* First, try object callbacks */
2814 r = node_callbacks_run(bus, m, n->callbacks, require_fallback, found_object);
2818 if (!m->interface || !m->member)
2821 /* Then, look for a known method */
2822 vtable_key.path = (char*) p;
2823 vtable_key.interface = m->interface;
2824 vtable_key.member = m->member;
2826 v = hashmap_get(bus->vtable_methods, &vtable_key);
2828 r = method_callbacks_run(bus, m, v, require_fallback, found_object);
2833 /* Then, look for a known property */
2834 if (streq(m->interface, "org.freedesktop.DBus.Properties")) {
2837 get = streq(m->member, "Get");
2839 if (get || streq(m->member, "Set")) {
2841 r = sd_bus_message_rewind(m, true);
2845 vtable_key.path = (char*) p;
2847 r = sd_bus_message_read(m, "ss", &vtable_key.interface, &vtable_key.member);
2851 v = hashmap_get(bus->vtable_properties, &vtable_key);
2853 r = property_get_set_callbacks_run(bus, m, v, require_fallback, get, found_object);
2858 } else if (streq(m->member, "GetAll")) {
2861 r = sd_bus_message_rewind(m, true);
2865 r = sd_bus_message_read(m, "s", &iface);
2872 r = property_get_all_callbacks_run(bus, m, n->vtables, require_fallback, iface, found_object);
2877 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
2879 r = process_introspect(bus, m, n, require_fallback, found_object);
2883 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.ObjectManager", "GetManagedObjects")) {
2885 r = process_get_managed_objects(bus, m, n, require_fallback, found_object);
2890 if (!*found_object) {
2891 r = bus_node_exists(bus, n, m->path, require_fallback);
2896 *found_object = true;
2902 static int process_object(sd_bus *bus, sd_bus_message *m) {
2905 bool found_object = false;
2910 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
2916 if (hashmap_isempty(bus->nodes))
2919 pl = strlen(m->path);
2923 bus->nodes_modified = false;
2925 r = object_find_and_run(bus, m, m->path, false, &found_object);
2929 /* Look for fallback prefixes */
2937 if (bus->nodes_modified)
2940 e = strrchr(p, '/');
2947 r = object_find_and_run(bus, m, p, true, &found_object);
2952 } while (bus->nodes_modified);
2957 if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "Get") ||
2958 sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "Set"))
2959 r = sd_bus_reply_method_errorf(
2961 "org.freedesktop.DBus.Error.UnknownProperty",
2962 "Unknown property or interface.");
2964 r = sd_bus_reply_method_errorf(
2966 "org.freedesktop.DBus.Error.UnknownMethod",
2967 "Unknown method '%s' or interface '%s'.", m->member, m->interface);
2975 static int process_message(sd_bus *bus, sd_bus_message *m) {
2981 bus->iteration_counter++;
2983 r = process_hello(bus, m);
2987 r = process_reply(bus, m);
2991 r = process_filter(bus, m);
2995 r = process_match(bus, m);
2999 r = process_builtin(bus, m);
3003 return process_object(bus, m);
3006 static int process_running(sd_bus *bus, sd_bus_message **ret) {
3007 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
3011 assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
3013 r = process_timeout(bus);
3017 r = dispatch_wqueue(bus);
3021 r = dispatch_rqueue(bus, &m);
3027 r = process_message(bus, m);
3032 r = sd_bus_message_rewind(m, true);
3041 if (m->header->type == SD_BUS_MESSAGE_TYPE_METHOD_CALL) {
3043 r = sd_bus_reply_method_errorf(
3045 "org.freedesktop.DBus.Error.UnknownObject",
3046 "Unknown object '%s'.", m->path);
3060 int sd_bus_process(sd_bus *bus, sd_bus_message **ret) {
3063 /* Returns 0 when we didn't do anything. This should cause the
3064 * caller to invoke sd_bus_wait() before returning the next
3065 * time. Returns > 0 when we did something, which possibly
3066 * means *ret is filled in with an unprocessed message. */
3070 if (bus_pid_changed(bus))
3073 /* We don't allow recursively invoking sd_bus_process(). */
3074 if (bus->processing)
3077 switch (bus->state) {
3084 r = bus_socket_process_opening(bus);
3091 case BUS_AUTHENTICATING:
3093 r = bus_socket_process_authenticating(bus);
3103 bus->processing = true;
3104 r = process_running(bus, ret);
3105 bus->processing = false;
3110 assert_not_reached("Unknown state");
3113 static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec) {
3114 struct pollfd p[2] = {};
3121 if (!BUS_IS_OPEN(bus->state))
3124 e = sd_bus_get_events(bus);
3131 r = sd_bus_get_timeout(bus, &until);
3138 nw = now(CLOCK_MONOTONIC);
3139 m = until > nw ? until - nw : 0;
3142 if (timeout_usec != (uint64_t) -1 && (m == (uint64_t) -1 || timeout_usec < m))
3145 p[0].fd = bus->input_fd;
3146 if (bus->output_fd == bus->input_fd) {
3150 p[0].events = e & POLLIN;
3151 p[1].fd = bus->output_fd;
3152 p[1].events = e & POLLOUT;
3156 r = ppoll(p, n, m == (uint64_t) -1 ? NULL : timespec_store(&ts, m), NULL);
3160 return r > 0 ? 1 : 0;
3163 int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec) {
3167 if (!BUS_IS_OPEN(bus->state))
3169 if (bus_pid_changed(bus))
3172 if (bus->rqueue_size > 0)
3175 return bus_poll(bus, false, timeout_usec);
3178 int sd_bus_flush(sd_bus *bus) {
3183 if (!BUS_IS_OPEN(bus->state))
3185 if (bus_pid_changed(bus))
3188 r = bus_ensure_running(bus);
3192 if (bus->wqueue_size <= 0)
3196 r = dispatch_wqueue(bus);
3200 if (bus->wqueue_size <= 0)
3203 r = bus_poll(bus, false, (uint64_t) -1);
3209 int sd_bus_add_filter(sd_bus *bus, sd_bus_message_handler_t callback, void *userdata) {
3210 struct filter_callback *f;
3216 if (bus_pid_changed(bus))
3219 f = new0(struct filter_callback, 1);
3222 f->callback = callback;
3223 f->userdata = userdata;
3225 bus->filter_callbacks_modified = true;
3226 LIST_PREPEND(struct filter_callback, callbacks, bus->filter_callbacks, f);
3230 int sd_bus_remove_filter(sd_bus *bus, sd_bus_message_handler_t callback, void *userdata) {
3231 struct filter_callback *f;
3237 if (bus_pid_changed(bus))
3240 LIST_FOREACH(callbacks, f, bus->filter_callbacks) {
3241 if (f->callback == callback && f->userdata == userdata) {
3242 bus->filter_callbacks_modified = true;
3243 LIST_REMOVE(struct filter_callback, callbacks, bus->filter_callbacks, f);
3252 static struct node *bus_node_allocate(sd_bus *bus, const char *path) {
3253 struct node *n, *parent;
3260 assert(path[0] == '/');
3262 n = hashmap_get(bus->nodes, path);
3266 r = hashmap_ensure_allocated(&bus->nodes, string_hash_func, string_compare_func);
3274 if (streq(path, "/"))
3277 e = strrchr(path, '/');
3280 p = strndupa(path, MAX(1, path - e));
3282 parent = bus_node_allocate(bus, p);
3289 n = new0(struct node, 1);
3296 r = hashmap_put(bus->nodes, s, n);
3304 LIST_PREPEND(struct node, siblings, parent->child, n);
3309 static void bus_node_gc(sd_bus *b, struct node *n) {
3322 assert(hashmap_remove(b->nodes, n->path) == n);
3325 LIST_REMOVE(struct node, siblings, n->parent->child, n);
3328 bus_node_gc(b, n->parent);
3332 static int bus_add_object(
3336 sd_bus_message_handler_t callback,
3339 struct node_callback *c;
3345 if (!object_path_is_valid(path))
3349 if (bus_pid_changed(b))
3352 n = bus_node_allocate(b, path);
3356 c = new0(struct node_callback, 1);
3363 c->callback = callback;
3364 c->userdata = userdata;
3365 c->is_fallback = fallback;
3367 LIST_PREPEND(struct node_callback, callbacks, n->callbacks, c);
3376 static int bus_remove_object(
3380 sd_bus_message_handler_t callback,
3383 struct node_callback *c;
3388 if (!object_path_is_valid(path))
3392 if (bus_pid_changed(bus))
3395 n = hashmap_get(bus->nodes, path);
3399 LIST_FOREACH(callbacks, c, n->callbacks)
3400 if (c->callback == callback && c->userdata == userdata && c->is_fallback == fallback)
3405 LIST_REMOVE(struct node_callback, callbacks, n->callbacks, c);
3408 bus_node_gc(bus, n);
3413 int sd_bus_add_object(sd_bus *bus, const char *path, sd_bus_message_handler_t callback, void *userdata) {
3414 return bus_add_object(bus, false, path, callback, userdata);
3417 int sd_bus_remove_object(sd_bus *bus, const char *path, sd_bus_message_handler_t callback, void *userdata) {
3418 return bus_remove_object(bus, false, path, callback, userdata);
3421 int sd_bus_add_fallback(sd_bus *bus, const char *prefix, sd_bus_message_handler_t callback, void *userdata) {
3422 return bus_add_object(bus, true, prefix, callback, userdata);
3425 int sd_bus_remove_fallback(sd_bus *bus, const char *prefix, sd_bus_message_handler_t callback, void *userdata) {
3426 return bus_remove_object(bus, true, prefix, callback, userdata);
3429 int sd_bus_add_match(sd_bus *bus, const char *match, sd_bus_message_handler_t callback, void *userdata) {
3430 struct bus_match_component *components = NULL;
3431 unsigned n_components = 0;
3432 uint64_t cookie = 0;
3439 if (bus_pid_changed(bus))
3442 r = bus_match_parse(match, &components, &n_components);
3446 if (bus->bus_client) {
3447 cookie = ++bus->match_cookie;
3449 r = bus_add_match_internal(bus, match, components, n_components, cookie);
3454 bus->match_callbacks_modified = true;
3455 r = bus_match_add(&bus->match_callbacks, components, n_components, callback, userdata, cookie, NULL);
3457 if (bus->bus_client)
3458 bus_remove_match_internal(bus, match, cookie);
3462 bus_match_parse_free(components, n_components);
3466 int sd_bus_remove_match(sd_bus *bus, const char *match, sd_bus_message_handler_t callback, void *userdata) {
3467 struct bus_match_component *components = NULL;
3468 unsigned n_components = 0;
3470 uint64_t cookie = 0;
3476 if (bus_pid_changed(bus))
3479 r = bus_match_parse(match, &components, &n_components);
3483 bus->match_callbacks_modified = true;
3484 r = bus_match_remove(&bus->match_callbacks, components, n_components, callback, userdata, &cookie);
3486 if (bus->bus_client)
3487 q = bus_remove_match_internal(bus, match, cookie);
3489 bus_match_parse_free(components, n_components);
3491 return r < 0 ? r : q;
3494 int sd_bus_emit_signal(
3497 const char *interface,
3499 const char *types, ...) {
3501 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
3506 if (!BUS_IS_OPEN(bus->state))
3508 if (bus_pid_changed(bus))
3511 r = sd_bus_message_new_signal(bus, path, interface, member, &m);
3515 if (!isempty(types)) {
3518 va_start(ap, types);
3519 r = bus_message_append_ap(m, types, ap);
3525 return sd_bus_send(bus, m, NULL);
3528 int sd_bus_call_method(
3530 const char *destination,
3532 const char *interface,
3534 sd_bus_error *error,
3535 sd_bus_message **reply,
3536 const char *types, ...) {
3538 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
3544 if (!BUS_IS_OPEN(bus->state))
3546 if (bus_pid_changed(bus))
3549 r = sd_bus_message_new_method_call(bus, destination, path, interface, member, &m);
3553 if (!isempty(types)) {
3556 va_start(ap, types);
3557 r = bus_message_append_ap(m, types, ap);
3563 return sd_bus_send_with_reply_and_block(bus, m, 0, error, reply);
3566 int sd_bus_reply_method_return(
3568 sd_bus_message *call,
3569 const char *types, ...) {
3571 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
3580 if (call->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
3582 if (!BUS_IS_OPEN(bus->state))
3584 if (bus_pid_changed(bus))
3587 if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
3590 r = sd_bus_message_new_method_return(bus, call, &m);
3594 if (!isempty(types)) {
3597 va_start(ap, types);
3598 r = bus_message_append_ap(m, types, ap);
3604 return sd_bus_send(bus, m, NULL);
3607 int sd_bus_reply_method_error(
3609 sd_bus_message *call,
3610 const sd_bus_error *e) {
3612 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
3621 if (call->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
3623 if (!sd_bus_error_is_set(e))
3625 if (!BUS_IS_OPEN(bus->state))
3627 if (bus_pid_changed(bus))
3630 if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
3633 r = sd_bus_message_new_method_error(bus, call, e, &m);
3637 return sd_bus_send(bus, m, NULL);
3640 int sd_bus_reply_method_errorf(
3642 sd_bus_message *call,
3647 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3657 va_start(ap, format);
3658 r = vasprintf(&m, format, ap);
3669 error.need_free = true;
3671 return sd_bus_reply_method_error(bus, call, &error);
3674 bool bus_pid_changed(sd_bus *bus) {
3677 /* We don't support people creating a bus connection and
3678 * keeping it around over a fork(). Let's complain. */
3680 return bus->original_pid != getpid();
3683 static void free_node_vtable(sd_bus *bus, struct node_vtable *w) {
3689 if (w->interface && w->node && w->vtable) {
3690 const sd_bus_vtable *v;
3692 for (v = w->vtable; v->type != _SD_BUS_VTABLE_END; v++) {
3693 struct vtable_member *x = NULL;
3697 case _SD_BUS_VTABLE_METHOD: {
3698 struct vtable_member key;
3700 key.path = w->node->path;
3701 key.interface = w->interface;
3702 key.member = v->method.member;
3704 x = hashmap_remove(bus->vtable_methods, &key);
3708 case _SD_BUS_VTABLE_PROPERTY:
3709 case _SD_BUS_VTABLE_WRITABLE_PROPERTY: {
3710 struct vtable_member key;
3712 key.path = w->node->path;
3713 key.interface = w->interface;
3714 key.member = v->property.member;
3715 x = hashmap_remove(bus->vtable_properties, &key);
3727 static unsigned vtable_member_hash_func(const void *a) {
3728 const struct vtable_member *m = a;
3731 string_hash_func(m->path) ^
3732 string_hash_func(m->interface) ^
3733 string_hash_func(m->member);
3736 static int vtable_member_compare_func(const void *a, const void *b) {
3737 const struct vtable_member *x = a, *y = b;
3740 r = strcmp(x->path, y->path);
3744 r = strcmp(x->interface, y->interface);
3748 return strcmp(x->member, y->member);
3751 static int add_object_vtable_internal(
3754 const char *interface,
3755 const sd_bus_vtable *vtable,
3757 sd_bus_object_find_t find,
3760 struct node_vtable *c = NULL, *i;
3761 const sd_bus_vtable *v;
3767 if (!object_path_is_valid(path))
3769 if (!interface_name_is_valid(interface))
3771 if (!vtable || vtable[0].type != _SD_BUS_VTABLE_START || vtable[0].start.element_size != sizeof(struct sd_bus_vtable))
3773 if (bus_pid_changed(bus))
3776 r = hashmap_ensure_allocated(&bus->vtable_methods, vtable_member_hash_func, vtable_member_compare_func);
3780 r = hashmap_ensure_allocated(&bus->vtable_properties, vtable_member_hash_func, vtable_member_compare_func);
3784 n = bus_node_allocate(bus, path);
3788 LIST_FOREACH(vtables, i, n->vtables) {
3789 if (streq(i->interface, interface)) {
3794 if (i->is_fallback != fallback) {
3800 c = new0(struct node_vtable, 1);
3807 c->is_fallback = fallback;
3809 c->userdata = userdata;
3812 c->interface = strdup(interface);
3813 if (!c->interface) {
3818 for (v = c->vtable+1; v->type != _SD_BUS_VTABLE_END; v++) {
3822 case _SD_BUS_VTABLE_METHOD: {
3823 struct vtable_member *m;
3825 if (!member_name_is_valid(v->method.member) ||
3826 !signature_is_valid(strempty(v->method.signature), false) ||
3827 !signature_is_valid(strempty(v->method.result), false) ||
3828 !(v->method.handler || (isempty(v->method.signature) && isempty(v->method.result))) ||
3829 v->flags & (SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE|SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY)) {
3834 m = new0(struct vtable_member, 1);
3842 m->interface = c->interface;
3843 m->member = v->method.member;
3846 r = hashmap_put(bus->vtable_methods, m, m);
3855 case _SD_BUS_VTABLE_WRITABLE_PROPERTY:
3857 if (!(v->property.set || bus_type_is_basic(v->property.signature[0]))) {
3864 case _SD_BUS_VTABLE_PROPERTY: {
3865 struct vtable_member *m;
3867 if (!member_name_is_valid(v->property.member) ||
3868 !signature_is_single(v->property.signature, false) ||
3869 !(v->property.get || bus_type_is_basic(v->property.signature[0])) ||
3870 v->flags & SD_BUS_VTABLE_METHOD_NO_REPLY ||
3871 (v->flags & SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY && !(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE))) {
3877 m = new0(struct vtable_member, 1);
3885 m->interface = c->interface;
3886 m->member = v->property.member;
3889 r = hashmap_put(bus->vtable_properties, m, m);
3898 case _SD_BUS_VTABLE_SIGNAL:
3900 if (!member_name_is_valid(v->signal.member) ||
3901 !signature_is_single(strempty(v->signal.signature), false)) {
3914 LIST_PREPEND(struct node_vtable, vtables, n->vtables, c);
3919 free_node_vtable(bus, c);
3921 bus_node_gc(bus, n);
3925 static int remove_object_vtable_internal(
3928 const char *interface,
3931 struct node_vtable *c;
3936 if (!object_path_is_valid(path))
3938 if (!interface_name_is_valid(interface))
3940 if (bus_pid_changed(bus))
3943 n = hashmap_get(bus->nodes, path);
3947 LIST_FOREACH(vtables, c, n->vtables)
3948 if (streq(c->interface, interface) && c->is_fallback == fallback)
3954 LIST_REMOVE(struct node_vtable, vtables, n->vtables, c);
3956 free_node_vtable(bus, c);
3960 int sd_bus_add_object_vtable(
3963 const char *interface,
3964 const sd_bus_vtable *vtable,
3967 return add_object_vtable_internal(bus, path, interface, vtable, false, NULL, userdata);
3970 int sd_bus_remove_object_vtable(
3973 const char *interface) {
3975 return remove_object_vtable_internal(bus, path, interface, false);
3978 int sd_bus_add_fallback_vtable(
3981 const char *interface,
3982 const sd_bus_vtable *vtable,
3983 sd_bus_object_find_t find,
3986 return add_object_vtable_internal(bus, path, interface, vtable, true, find, userdata);
3989 int sd_bus_remove_fallback_vtable(
3992 const char *interface) {
3994 return remove_object_vtable_internal(bus, path, interface, true);
3997 int sd_bus_add_node_enumerator(
4000 sd_bus_node_enumerator_t callback,
4003 struct node_enumerator *c;
4009 if (!object_path_is_valid(path))
4013 if (bus_pid_changed(bus))
4016 n = bus_node_allocate(bus, path);
4020 c = new0(struct node_enumerator, 1);
4027 c->callback = callback;
4028 c->userdata = userdata;
4030 LIST_PREPEND(struct node_enumerator, enumerators, n->enumerators, c);
4035 bus_node_gc(bus, n);
4039 int sd_bus_remove_node_enumerator(
4042 sd_bus_node_enumerator_t callback,
4045 struct node_enumerator *c;
4050 if (!object_path_is_valid(path))
4054 if (bus_pid_changed(bus))
4057 n = hashmap_get(bus->nodes, path);
4061 LIST_FOREACH(enumerators, c, n->enumerators)
4062 if (c->callback == callback && c->userdata == userdata)
4068 LIST_REMOVE(struct node_enumerator, enumerators, n->enumerators, c);
4071 bus_node_gc(bus, n);
4076 static int emit_properties_changed_on_interface(
4080 const char *interface,
4081 bool require_fallback,
4084 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4085 bool has_invalidating = false;
4086 struct vtable_member key;
4087 struct node_vtable *c;
4097 n = hashmap_get(bus->nodes, prefix);
4101 LIST_FOREACH(vtables, c, n->vtables) {
4102 if (require_fallback && !c->is_fallback)
4105 if (streq(c->interface, interface))
4112 r = node_vtable_get_userdata(bus, path, c, &u);
4116 r = sd_bus_message_new_signal(bus, path, "org.freedesktop.DBus.Properties", "PropertiesChanged", &m);
4120 r = sd_bus_message_append(m, "s", interface);
4124 r = sd_bus_message_open_container(m, 'a', "{sv}");
4129 key.interface = interface;
4131 STRV_FOREACH(property, names) {
4132 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4133 struct vtable_member *v;
4135 key.member = *property;
4136 v = hashmap_get(bus->vtable_properties, &key);
4140 assert(c == v->parent);
4142 if (!(v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE))
4144 if (v->vtable->flags & SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY) {
4145 has_invalidating = true;
4149 r = sd_bus_message_open_container(m, 'e', "sv");
4153 r = sd_bus_message_append(m, "s", *property);
4157 r = sd_bus_message_open_container(m, 'v', v->vtable->property.signature);
4161 r = invoke_property_get(bus, v->vtable, m->path, interface, *property, m, &error, vtable_property_convert_userdata(v->vtable, u));
4165 if (sd_bus_error_is_set(&error))
4166 return bus_error_to_errno(&error);
4168 r = sd_bus_message_close_container(m);
4172 r = sd_bus_message_close_container(m);
4177 r = sd_bus_message_close_container(m);
4181 r = sd_bus_message_open_container(m, 'a', "s");
4185 if (has_invalidating) {
4186 STRV_FOREACH(property, names) {
4187 struct vtable_member *v;
4189 key.member = *property;
4190 assert_se(v = hashmap_get(bus->vtable_properties, &key));
4191 assert(c == v->parent);
4193 if (!(v->vtable->flags & SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY))
4196 r = sd_bus_message_append(m, "s", *property);
4202 r = sd_bus_message_close_container(m);
4206 r = sd_bus_send(bus, m, NULL);
4213 int sd_bus_emit_properties_changed_strv(sd_bus *bus, const char *path, const char *interface, char **names) {
4219 if (!object_path_is_valid(path))
4221 if (!interface_name_is_valid(interface))
4224 r = emit_properties_changed_on_interface(bus, path, path, interface, false, names);
4239 e = strrchr(p, '/');
4246 r = emit_properties_changed_on_interface(bus, p, path, interface, true, names);
4255 int sd_bus_emit_properties_changed(sd_bus *bus, const char *path, const char *interface, const char *name, ...) {
4256 _cleanup_strv_free_ char **names = NULL;
4260 names = strv_new_ap(name, ap);
4266 return sd_bus_emit_properties_changed_strv(bus, path, interface, names);
4269 int sd_bus_emit_interfaces_added(sd_bus *bus, const char *path, const char *interfaces, ...) {
4273 int sd_bus_emit_interfaces_removed(sd_bus *bus, const char *path, const char *interfaces, ...) {
4277 int sd_bus_get_property(
4279 const char *destination,
4281 const char *interface,
4283 sd_bus_error *error,
4284 sd_bus_message **reply,
4287 sd_bus_message *rep = NULL;
4290 if (interface && !interface_name_is_valid(interface))
4292 if (!member_name_is_valid(member))
4294 if (!signature_is_single(type, false))
4299 r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &rep, "ss", strempty(interface), member);
4303 r = sd_bus_message_enter_container(rep, 'v', type);
4305 sd_bus_message_unref(rep);
4313 int sd_bus_set_property(
4315 const char *destination,
4317 const char *interface,
4319 sd_bus_error *error,
4320 const char *type, ...) {
4322 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4326 if (interface && !interface_name_is_valid(interface))
4328 if (!member_name_is_valid(member))
4330 if (!signature_is_single(type, false))
4333 r = sd_bus_message_new_method_call(bus, destination, path, "org.freedesktop.DBus.Properties", "Set", &m);
4337 r = sd_bus_message_append(m, "ss", strempty(interface), member);
4341 r = sd_bus_message_open_container(m, 'v', type);
4346 r = bus_message_append_ap(m, type, ap);
4351 r = sd_bus_message_close_container(m);
4355 return sd_bus_send_with_reply_and_block(bus, m, 0, error, NULL);
4358 int sd_bus_add_object_manager(sd_bus *bus, const char *path) {
4363 if (!object_path_is_valid(path))
4365 if (bus_pid_changed(bus))
4368 n = bus_node_allocate(bus, path);
4372 n->object_manager = true;
4376 int sd_bus_remove_object_manager(sd_bus *bus, const char *path) {
4381 if (!object_path_is_valid(path))
4383 if (bus_pid_changed(bus))
4386 n = hashmap_get(bus->nodes, path);
4390 if (!n->object_manager)
4393 n->object_manager = false;
4394 bus_node_gc(bus, n);