]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-bus/sd-bus.c
systemd-delta: count overrides only of the requested type
[thirdparty/systemd.git] / src / libsystemd-bus / sd-bus.c
CommitLineData
de1c301e
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013 Lennart Poettering
7
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.
12
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.
17
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/>.
20***/
21
22#include <endian.h>
23#include <assert.h>
24#include <stdlib.h>
25#include <unistd.h>
26#include <netdb.h>
27#include <sys/poll.h>
28#include <byteswap.h>
29
30#include "util.h"
31#include "macro.h"
2fd9ae2e 32#include "strv.h"
0a72c2bd 33#include "set.h"
6c03089c 34#include "missing.h"
de1c301e
LP
35
36#include "sd-bus.h"
37#include "bus-internal.h"
38#include "bus-message.h"
39#include "bus-type.h"
a7e3212d 40#include "bus-socket.h"
6629161f 41#include "bus-kernel.h"
392d5b37 42#include "bus-control.h"
de1c301e 43
e3017af9
LP
44static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec);
45
de1c301e
LP
46static void bus_free(sd_bus *b) {
47 struct filter_callback *f;
a652755d 48 struct object_callback *c;
89ffcd2a 49 unsigned i;
de1c301e
LP
50
51 assert(b);
52
e82c9509 53 sd_bus_close(b);
de1c301e
LP
54
55 free(b->rbuffer);
89ffcd2a 56 free(b->unique_name);
2181a7f5 57 free(b->auth_buffer);
89ffcd2a 58 free(b->address);
e9a967f9 59 free(b->kernel);
89ffcd2a 60
2fd9ae2e
LP
61 free(b->exec_path);
62 strv_free(b->exec_argv);
63
2c93b4ef
LP
64 close_many(b->fds, b->n_fds);
65 free(b->fds);
66
89ffcd2a
LP
67 for (i = 0; i < b->rqueue_size; i++)
68 sd_bus_message_unref(b->rqueue[i]);
de1c301e 69 free(b->rqueue);
89ffcd2a
LP
70
71 for (i = 0; i < b->wqueue_size; i++)
72 sd_bus_message_unref(b->wqueue[i]);
de1c301e 73 free(b->wqueue);
de1c301e
LP
74
75 hashmap_free_free(b->reply_callbacks);
e3017af9 76 prioq_free(b->reply_callbacks_prioq);
de1c301e
LP
77
78 while ((f = b->filter_callbacks)) {
79 LIST_REMOVE(struct filter_callback, callbacks, b->filter_callbacks, f);
80 free(f);
81 }
82
a652755d
LP
83 while ((c = hashmap_steal_first(b->object_callbacks))) {
84 free(c->path);
85 free(c);
86 }
87
88 hashmap_free(b->object_callbacks);
392d5b37
LP
89 bus_match_free(&b->match_callbacks);
90
bc7fd8cd
LP
91 bus_kernel_flush_memfd(b);
92
de1c301e
LP
93 free(b);
94}
95
021a1e78 96int sd_bus_new(sd_bus **ret) {
de1c301e
LP
97 sd_bus *r;
98
021a1e78
LP
99 if (!ret)
100 return -EINVAL;
101
de1c301e
LP
102 r = new0(sd_bus, 1);
103 if (!r)
021a1e78 104 return -ENOMEM;
de1c301e 105
e4ee6e5c 106 r->n_ref = REFCNT_INIT;
e82c9509 107 r->input_fd = r->output_fd = -1;
de1c301e 108 r->message_version = 1;
021a1e78 109 r->negotiate_fds = true;
de1c301e
LP
110
111 /* We guarantee that wqueue always has space for at least one
112 * entry */
113 r->wqueue = new(sd_bus_message*, 1);
114 if (!r->wqueue) {
115 free(r);
021a1e78 116 return -ENOMEM;
de1c301e
LP
117 }
118
021a1e78
LP
119 *ret = r;
120 return 0;
121}
122
123int sd_bus_set_address(sd_bus *bus, const char *address) {
124 char *a;
125
126 if (!bus)
127 return -EINVAL;
128 if (bus->state != BUS_UNSET)
129 return -EPERM;
130 if (!address)
131 return -EINVAL;
132
133 a = strdup(address);
134 if (!a)
135 return -ENOMEM;
136
137 free(bus->address);
138 bus->address = a;
139
140 return 0;
141}
142
e82c9509 143int sd_bus_set_fd(sd_bus *bus, int input_fd, int output_fd) {
021a1e78
LP
144 if (!bus)
145 return -EINVAL;
146 if (bus->state != BUS_UNSET)
147 return -EPERM;
e82c9509
LP
148 if (input_fd < 0)
149 return -EINVAL;
150 if (output_fd < 0)
021a1e78
LP
151 return -EINVAL;
152
e82c9509
LP
153 bus->input_fd = input_fd;
154 bus->output_fd = output_fd;
021a1e78
LP
155 return 0;
156}
157
2fd9ae2e
LP
158int sd_bus_set_exec(sd_bus *bus, const char *path, char *const argv[]) {
159 char *p, **a;
160
161 if (!bus)
162 return -EINVAL;
163 if (bus->state != BUS_UNSET)
164 return -EPERM;
165 if (!path)
166 return -EINVAL;
167 if (strv_isempty(argv))
168 return -EINVAL;
169
170 p = strdup(path);
171 if (!p)
172 return -ENOMEM;
173
174 a = strv_copy(argv);
175 if (!a) {
176 free(p);
177 return -ENOMEM;
178 }
179
180 free(bus->exec_path);
181 strv_free(bus->exec_argv);
182
183 bus->exec_path = p;
184 bus->exec_argv = a;
185
186 return 0;
187}
188
94bbf1ba 189int sd_bus_set_bus_client(sd_bus *bus, int b) {
021a1e78
LP
190 if (!bus)
191 return -EINVAL;
192 if (bus->state != BUS_UNSET)
193 return -EPERM;
194
94bbf1ba 195 bus->bus_client = !!b;
021a1e78
LP
196 return 0;
197}
198
199int sd_bus_set_negotiate_fds(sd_bus *bus, int b) {
200 if (!bus)
201 return -EINVAL;
202 if (bus->state != BUS_UNSET)
203 return -EPERM;
204
205 bus->negotiate_fds = !!b;
206 return 0;
207}
de1c301e 208
98178d39 209int sd_bus_set_server(sd_bus *bus, int b, sd_id128_t server_id) {
2181a7f5
LP
210 if (!bus)
211 return -EINVAL;
98178d39 212 if (!b && !sd_id128_equal(server_id, SD_ID128_NULL))
2181a7f5
LP
213 return -EINVAL;
214 if (bus->state != BUS_UNSET)
215 return -EPERM;
216
217 bus->is_server = !!b;
98178d39 218 bus->server_id = server_id;
2181a7f5
LP
219 return 0;
220}
221
222int sd_bus_set_anonymous(sd_bus *bus, int b) {
223 if (!bus)
224 return -EINVAL;
225 if (bus->state != BUS_UNSET)
226 return -EPERM;
227
228 bus->anonymous_auth = !!b;
229 return 0;
230}
231
eb01ba5d 232static int hello_callback(sd_bus *bus, sd_bus_message *reply, void *userdata) {
de1c301e
LP
233 const char *s;
234 int r;
235
236 assert(bus);
021a1e78 237 assert(bus->state == BUS_HELLO);
de1c301e
LP
238 assert(reply);
239
eb01ba5d
LP
240 r = bus_message_to_errno(reply);
241 if (r < 0)
242 return r;
243
de1c301e
LP
244 r = sd_bus_message_read(reply, "s", &s);
245 if (r < 0)
246 return r;
247
dafb7591
LP
248 if (!service_name_is_valid(s) || s[0] != ':')
249 return -EBADMSG;
250
de1c301e
LP
251 bus->unique_name = strdup(s);
252 if (!bus->unique_name)
253 return -ENOMEM;
254
dafb7591
LP
255 bus->state = BUS_RUNNING;
256
de1c301e
LP
257 return 1;
258}
259
260static int bus_send_hello(sd_bus *bus) {
261 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
262 int r;
263
264 assert(bus);
265
6629161f 266 if (!bus->bus_client || bus->is_kernel)
021a1e78
LP
267 return 0;
268
de1c301e
LP
269 r = sd_bus_message_new_method_call(
270 bus,
271 "org.freedesktop.DBus",
272 "/",
273 "org.freedesktop.DBus",
274 "Hello",
275 &m);
276 if (r < 0)
277 return r;
278
9d373862 279 return sd_bus_send_with_reply(bus, m, hello_callback, NULL, 0, &bus->hello_serial);
de1c301e
LP
280}
281
a7e3212d 282int bus_start_running(sd_bus *bus) {
de1c301e
LP
283 assert(bus);
284
f08838da 285 if (bus->bus_client && !bus->is_kernel) {
de1c301e 286 bus->state = BUS_HELLO;
e3017af9 287 return 1;
de1c301e
LP
288 }
289
290 bus->state = BUS_RUNNING;
e3017af9 291 return 1;
de1c301e
LP
292}
293
294static int parse_address_key(const char **p, const char *key, char **value) {
295 size_t l, n = 0;
296 const char *a;
297 char *r = NULL;
298
299 assert(p);
300 assert(*p);
de1c301e
LP
301 assert(value);
302
2fd9ae2e
LP
303 if (key) {
304 l = strlen(key);
305 if (strncmp(*p, key, l) != 0)
306 return 0;
de1c301e 307
2fd9ae2e
LP
308 if ((*p)[l] != '=')
309 return 0;
de1c301e 310
2fd9ae2e
LP
311 if (*value)
312 return -EINVAL;
de1c301e 313
2fd9ae2e
LP
314 a = *p + l + 1;
315 } else
316 a = *p;
317
318 while (*a != ';' && *a != ',' && *a != 0) {
de1c301e
LP
319 char c, *t;
320
321 if (*a == '%') {
322 int x, y;
323
324 x = unhexchar(a[1]);
325 if (x < 0) {
326 free(r);
327 return x;
328 }
329
330 y = unhexchar(a[2]);
331 if (y < 0) {
332 free(r);
333 return y;
334 }
335
de1c301e 336 c = (char) ((x << 4) | y);
89ffcd2a
LP
337 a += 3;
338 } else {
de1c301e 339 c = *a;
89ffcd2a
LP
340 a++;
341 }
de1c301e 342
89ffcd2a 343 t = realloc(r, n + 2);
de1c301e
LP
344 if (!t) {
345 free(r);
346 return -ENOMEM;
347 }
348
349 r = t;
350 r[n++] = c;
351 }
352
89ffcd2a
LP
353 if (!r) {
354 r = strdup("");
355 if (!r)
356 return -ENOMEM;
357 } else
358 r[n] = 0;
359
360 if (*a == ',')
361 a++;
362
de1c301e 363 *p = a;
2fd9ae2e
LP
364
365 free(*value);
de1c301e 366 *value = r;
2fd9ae2e 367
de1c301e
LP
368 return 1;
369}
370
371static void skip_address_key(const char **p) {
372 assert(p);
373 assert(*p);
374
89ffcd2a
LP
375 *p += strcspn(*p, ",");
376
377 if (**p == ',')
378 (*p) ++;
de1c301e
LP
379}
380
2fd9ae2e
LP
381static int parse_unix_address(sd_bus *b, const char **p, char **guid) {
382 _cleanup_free_ char *path = NULL, *abstract = NULL;
383 size_t l;
de1c301e
LP
384 int r;
385
386 assert(b);
2fd9ae2e
LP
387 assert(p);
388 assert(*p);
389 assert(guid);
de1c301e 390
2fd9ae2e
LP
391 while (**p != 0 && **p != ';') {
392 r = parse_address_key(p, "guid", guid);
393 if (r < 0)
394 return r;
395 else if (r > 0)
396 continue;
de1c301e 397
2fd9ae2e
LP
398 r = parse_address_key(p, "path", &path);
399 if (r < 0)
400 return r;
401 else if (r > 0)
402 continue;
de1c301e 403
2fd9ae2e
LP
404 r = parse_address_key(p, "abstract", &abstract);
405 if (r < 0)
406 return r;
407 else if (r > 0)
408 continue;
de1c301e 409
2fd9ae2e
LP
410 skip_address_key(p);
411 }
de1c301e 412
2fd9ae2e
LP
413 if (!path && !abstract)
414 return -EINVAL;
de1c301e 415
2fd9ae2e
LP
416 if (path && abstract)
417 return -EINVAL;
418
419 if (path) {
420 l = strlen(path);
421 if (l > sizeof(b->sockaddr.un.sun_path))
422 return -E2BIG;
de1c301e 423
2fd9ae2e
LP
424 b->sockaddr.un.sun_family = AF_UNIX;
425 strncpy(b->sockaddr.un.sun_path, path, sizeof(b->sockaddr.un.sun_path));
426 b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + l;
427 } else if (abstract) {
428 l = strlen(abstract);
429 if (l > sizeof(b->sockaddr.un.sun_path) - 1)
430 return -E2BIG;
431
432 b->sockaddr.un.sun_family = AF_UNIX;
433 b->sockaddr.un.sun_path[0] = 0;
434 strncpy(b->sockaddr.un.sun_path+1, abstract, sizeof(b->sockaddr.un.sun_path)-1);
435 b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + 1 + l;
436 }
437
438 return 0;
439}
440
441static int parse_tcp_address(sd_bus *b, const char **p, char **guid) {
442 _cleanup_free_ char *host = NULL, *port = NULL, *family = NULL;
2fd9ae2e 443 int r;
b92bea5d
ZJS
444 struct addrinfo *result, hints = {
445 .ai_socktype = SOCK_STREAM,
446 .ai_flags = AI_ADDRCONFIG,
447 };
2fd9ae2e
LP
448
449 assert(b);
450 assert(p);
451 assert(*p);
452 assert(guid);
453
454 while (**p != 0 && **p != ';') {
455 r = parse_address_key(p, "guid", guid);
456 if (r < 0)
457 return r;
458 else if (r > 0)
459 continue;
460
461 r = parse_address_key(p, "host", &host);
462 if (r < 0)
463 return r;
464 else if (r > 0)
465 continue;
466
467 r = parse_address_key(p, "port", &port);
468 if (r < 0)
469 return r;
470 else if (r > 0)
471 continue;
472
473 r = parse_address_key(p, "family", &family);
474 if (r < 0)
475 return r;
476 else if (r > 0)
477 continue;
478
479 skip_address_key(p);
480 }
481
482 if (!host || !port)
483 return -EINVAL;
484
2fd9ae2e
LP
485 if (family) {
486 if (streq(family, "ipv4"))
487 hints.ai_family = AF_INET;
488 else if (streq(family, "ipv6"))
489 hints.ai_family = AF_INET6;
490 else
491 return -EINVAL;
492 }
493
494 r = getaddrinfo(host, port, &hints, &result);
495 if (r == EAI_SYSTEM)
496 return -errno;
497 else if (r != 0)
498 return -EADDRNOTAVAIL;
499
500 memcpy(&b->sockaddr, result->ai_addr, result->ai_addrlen);
501 b->sockaddr_size = result->ai_addrlen;
502
503 freeaddrinfo(result);
504
505 return 0;
506}
507
508static int parse_exec_address(sd_bus *b, const char **p, char **guid) {
509 char *path = NULL;
510 unsigned n_argv = 0, j;
511 char **argv = NULL;
512 int r;
513
514 assert(b);
515 assert(p);
516 assert(*p);
517 assert(guid);
518
519 while (**p != 0 && **p != ';') {
520 r = parse_address_key(p, "guid", guid);
521 if (r < 0)
522 goto fail;
523 else if (r > 0)
524 continue;
525
526 r = parse_address_key(p, "path", &path);
527 if (r < 0)
528 goto fail;
529 else if (r > 0)
530 continue;
531
532 if (startswith(*p, "argv")) {
533 unsigned ul;
534
535 errno = 0;
536 ul = strtoul(*p + 4, (char**) p, 10);
8333c77e 537 if (errno > 0 || **p != '=' || ul > 256) {
2fd9ae2e
LP
538 r = -EINVAL;
539 goto fail;
540 }
541
542 (*p) ++;
543
544 if (ul >= n_argv) {
545 char **x;
546
547 x = realloc(argv, sizeof(char*) * (ul + 2));
548 if (!x) {
549 r = -ENOMEM;
550 goto fail;
551 }
552
553 memset(x + n_argv, 0, sizeof(char*) * (ul - n_argv + 2));
554
555 argv = x;
556 n_argv = ul + 1;
557 }
558
559 r = parse_address_key(p, NULL, argv + ul);
de1c301e 560 if (r < 0)
2fd9ae2e 561 goto fail;
de1c301e 562
2fd9ae2e 563 continue;
de1c301e
LP
564 }
565
2fd9ae2e
LP
566 skip_address_key(p);
567 }
de1c301e 568
5a0f6033
LP
569 if (!path) {
570 r = -EINVAL;
2fd9ae2e 571 goto fail;
5a0f6033 572 }
de1c301e 573
2fd9ae2e
LP
574 /* Make sure there are no holes in the array, with the
575 * exception of argv[0] */
576 for (j = 1; j < n_argv; j++)
577 if (!argv[j]) {
578 r = -EINVAL;
579 goto fail;
580 }
581
582 if (argv && argv[0] == NULL) {
583 argv[0] = strdup(path);
584 if (!argv[0]) {
585 r = -ENOMEM;
586 goto fail;
587 }
588 }
de1c301e 589
2fd9ae2e
LP
590 b->exec_path = path;
591 b->exec_argv = argv;
592 return 0;
de1c301e 593
2fd9ae2e
LP
594fail:
595 for (j = 0; j < n_argv; j++)
596 free(argv[j]);
597
598 free(argv);
599 free(path);
600 return r;
601}
602
6629161f
LP
603static int parse_kernel_address(sd_bus *b, const char **p, char **guid) {
604 _cleanup_free_ char *path = NULL;
605 int r;
606
607 assert(b);
608 assert(p);
609 assert(*p);
610 assert(guid);
611
612 while (**p != 0 && **p != ';') {
613 r = parse_address_key(p, "guid", guid);
614 if (r < 0)
615 return r;
616 else if (r > 0)
617 continue;
618
619 r = parse_address_key(p, "path", &path);
620 if (r < 0)
621 return r;
622 else if (r > 0)
623 continue;
624
625 skip_address_key(p);
626 }
627
628 if (!path)
629 return -EINVAL;
630
631 free(b->kernel);
632 b->kernel = path;
633 path = NULL;
634
635 return 0;
636}
637
2fd9ae2e
LP
638static void bus_reset_parsed_address(sd_bus *b) {
639 assert(b);
640
641 zero(b->sockaddr);
642 b->sockaddr_size = 0;
643 strv_free(b->exec_argv);
644 free(b->exec_path);
645 b->exec_path = NULL;
646 b->exec_argv = NULL;
98178d39 647 b->server_id = SD_ID128_NULL;
6629161f
LP
648 free(b->kernel);
649 b->kernel = NULL;
2fd9ae2e
LP
650}
651
652static int bus_parse_next_address(sd_bus *b) {
653 _cleanup_free_ char *guid = NULL;
654 const char *a;
655 int r;
656
657 assert(b);
658
659 if (!b->address)
660 return 0;
661 if (b->address[b->address_index] == 0)
662 return 0;
663
664 bus_reset_parsed_address(b);
665
666 a = b->address + b->address_index;
de1c301e 667
2fd9ae2e 668 while (*a != 0) {
de1c301e 669
2fd9ae2e
LP
670 if (*a == ';') {
671 a++;
672 continue;
de1c301e
LP
673 }
674
2fd9ae2e
LP
675 if (startswith(a, "unix:")) {
676 a += 5;
de1c301e 677
2fd9ae2e 678 r = parse_unix_address(b, &a, &guid);
de1c301e
LP
679 if (r < 0)
680 return r;
2fd9ae2e 681 break;
de1c301e 682
2fd9ae2e 683 } else if (startswith(a, "tcp:")) {
de1c301e 684
2fd9ae2e
LP
685 a += 4;
686 r = parse_tcp_address(b, &a, &guid);
de1c301e
LP
687 if (r < 0)
688 return r;
de1c301e 689
2fd9ae2e
LP
690 break;
691
692 } else if (startswith(a, "unixexec:")) {
693
694 a += 9;
695 r = parse_exec_address(b, &a, &guid);
de1c301e
LP
696 if (r < 0)
697 return r;
de1c301e 698
2fd9ae2e 699 break;
de1c301e 700
6629161f
LP
701 } else if (startswith(a, "kernel:")) {
702
703 a += 7;
704 r = parse_kernel_address(b, &a, &guid);
705 if (r < 0)
706 return r;
707
708 break;
de1c301e
LP
709 }
710
2fd9ae2e
LP
711 a = strchr(a, ';');
712 if (!a)
713 return 0;
de1c301e
LP
714 }
715
716 if (guid) {
98178d39 717 r = sd_id128_from_string(guid, &b->server_id);
de1c301e
LP
718 if (r < 0)
719 return r;
720 }
721
2fd9ae2e 722 b->address_index = a - b->address;
de1c301e
LP
723 return 1;
724}
725
a7e3212d 726static int bus_start_address(sd_bus *b) {
2fd9ae2e
LP
727 int r;
728
729 assert(b);
730
731 for (;;) {
e82c9509 732 sd_bus_close(b);
2fd9ae2e
LP
733
734 if (b->sockaddr.sa.sa_family != AF_UNSPEC) {
a7e3212d
LP
735
736 r = bus_socket_connect(b);
2fd9ae2e
LP
737 if (r >= 0)
738 return r;
739
740 b->last_connect_error = -r;
741
742 } else if (b->exec_path) {
743
a7e3212d 744 r = bus_socket_exec(b);
2fd9ae2e
LP
745 if (r >= 0)
746 return r;
747
6629161f
LP
748 b->last_connect_error = -r;
749 } else if (b->kernel) {
750
751 r = bus_kernel_connect(b);
752 if (r >= 0)
753 return r;
754
2fd9ae2e
LP
755 b->last_connect_error = -r;
756 }
757
758 r = bus_parse_next_address(b);
759 if (r < 0)
760 return r;
761 if (r == 0)
762 return b->last_connect_error ? -b->last_connect_error : -ECONNREFUSED;
de1c301e
LP
763 }
764}
765
a7e3212d
LP
766int bus_next_address(sd_bus *b) {
767 assert(b);
768
769 bus_reset_parsed_address(b);
770 return bus_start_address(b);
771}
772
021a1e78 773static int bus_start_fd(sd_bus *b) {
6629161f 774 struct stat st;
021a1e78
LP
775 int r;
776
777 assert(b);
e82c9509
LP
778 assert(b->input_fd >= 0);
779 assert(b->output_fd >= 0);
021a1e78 780
e82c9509 781 r = fd_nonblock(b->input_fd, true);
021a1e78
LP
782 if (r < 0)
783 return r;
784
e82c9509 785 r = fd_cloexec(b->input_fd, true);
021a1e78
LP
786 if (r < 0)
787 return r;
788
e82c9509
LP
789 if (b->input_fd != b->output_fd) {
790 r = fd_nonblock(b->output_fd, true);
791 if (r < 0)
792 return r;
793
794 r = fd_cloexec(b->output_fd, true);
795 if (r < 0)
796 return r;
797 }
798
6629161f
LP
799 if (fstat(b->input_fd, &st) < 0)
800 return -errno;
801
802 if (S_ISCHR(b->input_fd))
803 return bus_kernel_take_fd(b);
804 else
805 return bus_socket_take_fd(b);
021a1e78
LP
806}
807
808int sd_bus_start(sd_bus *bus) {
809 int r;
810
811 if (!bus)
812 return -EINVAL;
813 if (bus->state != BUS_UNSET)
814 return -EPERM;
815
816 bus->state = BUS_OPENING;
817
2181a7f5
LP
818 if (bus->is_server && bus->bus_client)
819 return -EINVAL;
820
e82c9509 821 if (bus->input_fd >= 0)
021a1e78 822 r = bus_start_fd(bus);
6629161f 823 else if (bus->address || bus->sockaddr.sa.sa_family != AF_UNSPEC || bus->exec_path || bus->kernel)
a7e3212d 824 r = bus_start_address(bus);
021a1e78
LP
825 else
826 return -EINVAL;
827
828 if (r < 0)
829 return r;
830
831 return bus_send_hello(bus);
832}
833
de1c301e
LP
834int sd_bus_open_system(sd_bus **ret) {
835 const char *e;
836 sd_bus *b;
837 int r;
838
839 if (!ret)
840 return -EINVAL;
841
021a1e78
LP
842 r = sd_bus_new(&b);
843 if (r < 0)
844 return r;
845
6c03089c 846 e = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
de1c301e 847 if (e) {
021a1e78 848 r = sd_bus_set_address(b, e);
de1c301e 849 if (r < 0)
021a1e78 850 goto fail;
89ffcd2a 851 } else {
89ffcd2a
LP
852 b->sockaddr.un.sun_family = AF_UNIX;
853 strncpy(b->sockaddr.un.sun_path, "/run/dbus/system_bus_socket", sizeof(b->sockaddr.un.sun_path));
854 b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/dbus/system_bus_socket") - 1;
89ffcd2a 855 }
de1c301e 856
94bbf1ba 857 b->bus_client = true;
021a1e78
LP
858
859 r = sd_bus_start(b);
860 if (r < 0)
861 goto fail;
de1c301e
LP
862
863 *ret = b;
864 return 0;
021a1e78
LP
865
866fail:
867 bus_free(b);
868 return r;
de1c301e
LP
869}
870
871int sd_bus_open_user(sd_bus **ret) {
872 const char *e;
873 sd_bus *b;
874 size_t l;
875 int r;
876
877 if (!ret)
878 return -EINVAL;
879
021a1e78
LP
880 r = sd_bus_new(&b);
881 if (r < 0)
882 return r;
883
6c03089c 884 e = secure_getenv("DBUS_SESSION_BUS_ADDRESS");
de1c301e 885 if (e) {
021a1e78 886 r = sd_bus_set_address(b, e);
de1c301e 887 if (r < 0)
021a1e78 888 goto fail;
89ffcd2a 889 } else {
6c03089c 890 e = secure_getenv("XDG_RUNTIME_DIR");
021a1e78
LP
891 if (!e) {
892 r = -ENOENT;
893 goto fail;
894 }
de1c301e 895
89ffcd2a 896 l = strlen(e);
021a1e78
LP
897 if (l + 4 > sizeof(b->sockaddr.un.sun_path)) {
898 r = -E2BIG;
899 goto fail;
900 }
de1c301e 901
89ffcd2a
LP
902 b->sockaddr.un.sun_family = AF_UNIX;
903 memcpy(mempcpy(b->sockaddr.un.sun_path, e, l), "/bus", 4);
904 b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + l + 4;
de1c301e
LP
905 }
906
94bbf1ba 907 b->bus_client = true;
de1c301e 908
021a1e78 909 r = sd_bus_start(b);
2571ead1
LP
910 if (r < 0)
911 goto fail;
de1c301e
LP
912
913 *ret = b;
914 return 0;
2571ead1
LP
915
916fail:
021a1e78 917 bus_free(b);
2571ead1 918 return r;
de1c301e
LP
919}
920
921void sd_bus_close(sd_bus *bus) {
922 if (!bus)
923 return;
de1c301e 924
e82c9509
LP
925 if (bus->input_fd >= 0)
926 close_nointr_nofail(bus->input_fd);
927 if (bus->output_fd >= 0 && bus->output_fd != bus->input_fd)
928 close_nointr_nofail(bus->output_fd);
929
930 bus->input_fd = bus->output_fd = -1;
de1c301e
LP
931}
932
933sd_bus *sd_bus_ref(sd_bus *bus) {
934 if (!bus)
935 return NULL;
936
e4ee6e5c 937 assert_se(REFCNT_INC(bus->n_ref) >= 2);
de1c301e 938
de1c301e
LP
939 return bus;
940}
941
942sd_bus *sd_bus_unref(sd_bus *bus) {
943 if (!bus)
944 return NULL;
945
e4ee6e5c 946 if (REFCNT_DEC(bus->n_ref) <= 0)
de1c301e
LP
947 bus_free(bus);
948
949 return NULL;
950}
951
e3017af9
LP
952int sd_bus_is_open(sd_bus *bus) {
953 if (!bus)
954 return -EINVAL;
955
e82c9509 956 return bus->state != BUS_UNSET && bus->input_fd >= 0;
e3017af9
LP
957}
958
d728d708
LP
959int sd_bus_can_send(sd_bus *bus, char type) {
960 int r;
961
de1c301e
LP
962 if (!bus)
963 return -EINVAL;
e82c9509 964 if (bus->output_fd < 0)
021a1e78 965 return -ENOTCONN;
de1c301e 966
d728d708 967 if (type == SD_BUS_TYPE_UNIX_FD) {
021a1e78
LP
968 if (!bus->negotiate_fds)
969 return 0;
970
20902f3e 971 r = bus_ensure_running(bus);
d728d708
LP
972 if (r < 0)
973 return r;
de1c301e 974
d728d708
LP
975 return bus->can_fds;
976 }
977
978 return bus_type_is_valid(type);
de1c301e
LP
979}
980
98178d39 981int sd_bus_get_server_id(sd_bus *bus, sd_id128_t *server_id) {
d728d708 982 int r;
de1c301e
LP
983
984 if (!bus)
985 return -EINVAL;
98178d39 986 if (!server_id)
d728d708 987 return -EINVAL;
de1c301e 988
20902f3e 989 r = bus_ensure_running(bus);
d728d708
LP
990 if (r < 0)
991 return r;
de1c301e 992
98178d39 993 *server_id = bus->server_id;
d728d708 994 return 0;
de1c301e
LP
995}
996
997static int bus_seal_message(sd_bus *b, sd_bus_message *m) {
998 assert(m);
999
89ffcd2a
LP
1000 if (m->header->version > b->message_version)
1001 return -EPERM;
1002
de1c301e
LP
1003 if (m->sealed)
1004 return 0;
1005
9a17484d 1006 return bus_message_seal(m, ++b->serial);
de1c301e
LP
1007}
1008
de1c301e 1009static int dispatch_wqueue(sd_bus *bus) {
e3017af9 1010 int r, ret = 0;
de1c301e
LP
1011
1012 assert(bus);
89ffcd2a 1013 assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
de1c301e 1014
e82c9509 1015 if (bus->output_fd < 0)
de1c301e
LP
1016 return -ENOTCONN;
1017
1018 while (bus->wqueue_size > 0) {
1019
6629161f
LP
1020 if (bus->is_kernel)
1021 r = bus_kernel_write_message(bus, bus->wqueue[0]);
1022 else
1023 r = bus_socket_write_message(bus, bus->wqueue[0], &bus->windex);
1024
de1c301e
LP
1025 if (r < 0) {
1026 sd_bus_close(bus);
1027 return r;
1028 } else if (r == 0)
e3017af9
LP
1029 /* Didn't do anything this time */
1030 return ret;
6629161f 1031 else if (bus->is_kernel || bus->windex >= BUS_MESSAGE_SIZE(bus->wqueue[0])) {
de1c301e
LP
1032 /* Fully written. Let's drop the entry from
1033 * the queue.
1034 *
1035 * This isn't particularly optimized, but
1036 * well, this is supposed to be our worst-case
1037 * buffer only, and the socket buffer is
1038 * supposed to be our primary buffer, and if
1039 * it got full, then all bets are off
1040 * anyway. */
1041
1042 sd_bus_message_unref(bus->wqueue[0]);
1043 bus->wqueue_size --;
1044 memmove(bus->wqueue, bus->wqueue + 1, sizeof(sd_bus_message*) * bus->wqueue_size);
1045 bus->windex = 0;
1046
e3017af9 1047 ret = 1;
de1c301e
LP
1048 }
1049 }
1050
e3017af9 1051 return ret;
de1c301e
LP
1052}
1053
1054static int dispatch_rqueue(sd_bus *bus, sd_bus_message **m) {
2bf938c1 1055 sd_bus_message *z = NULL;
e3017af9 1056 int r, ret = 0;
de1c301e
LP
1057
1058 assert(bus);
1059 assert(m);
89ffcd2a 1060 assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
de1c301e 1061
e82c9509 1062 if (bus->input_fd < 0)
de1c301e
LP
1063 return -ENOTCONN;
1064
1065 if (bus->rqueue_size > 0) {
1066 /* Dispatch a queued message */
1067
1068 *m = bus->rqueue[0];
1069 bus->rqueue_size --;
1070 memmove(bus->rqueue, bus->rqueue + 1, sizeof(sd_bus_message*) * bus->rqueue_size);
1071 return 1;
1072 }
1073
1074 /* Try to read a new message */
e3017af9 1075 do {
6629161f
LP
1076 if (bus->is_kernel)
1077 r = bus_kernel_read_message(bus, &z);
1078 else
1079 r = bus_socket_read_message(bus, &z);
1080
e3017af9
LP
1081 if (r < 0) {
1082 sd_bus_close(bus);
1083 return r;
1084 }
1085 if (r == 0)
1086 return ret;
de1c301e 1087
e3017af9
LP
1088 r = 1;
1089 } while (!z);
1090
1091 *m = z;
1092 return 1;
de1c301e
LP
1093}
1094
1095int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *serial) {
1096 int r;
1097
1098 if (!bus)
1099 return -EINVAL;
021a1e78
LP
1100 if (bus->state == BUS_UNSET)
1101 return -ENOTCONN;
e82c9509 1102 if (bus->output_fd < 0)
de1c301e
LP
1103 return -ENOTCONN;
1104 if (!m)
1105 return -EINVAL;
021a1e78
LP
1106
1107 if (m->n_fds > 0) {
1108 r = sd_bus_can_send(bus, SD_BUS_TYPE_UNIX_FD);
1109 if (r < 0)
1110 return r;
1111 if (r == 0)
1112 return -ENOTSUP;
1113 }
de1c301e 1114
29f6aadd
LP
1115 /* If the serial number isn't kept, then we know that no reply
1116 * is expected */
1117 if (!serial && !m->sealed)
1118 m->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
1119
de1c301e
LP
1120 r = bus_seal_message(bus, m);
1121 if (r < 0)
1122 return r;
1123
5407f2de
LP
1124 /* If this is a reply and no reply was requested, then let's
1125 * suppress this, if we can */
1126 if (m->dont_send && !serial)
1127 return 0;
1128
89ffcd2a 1129 if ((bus->state == BUS_RUNNING || bus->state == BUS_HELLO) && bus->wqueue_size <= 0) {
de1c301e
LP
1130 size_t idx = 0;
1131
6629161f
LP
1132 if (bus->is_kernel)
1133 r = bus_kernel_write_message(bus, m);
1134 else
1135 r = bus_socket_write_message(bus, m, &idx);
1136
de1c301e
LP
1137 if (r < 0) {
1138 sd_bus_close(bus);
1139 return r;
6629161f 1140 } else if (!bus->is_kernel && idx < BUS_MESSAGE_SIZE(m)) {
de1c301e
LP
1141 /* Wasn't fully written. So let's remember how
1142 * much was written. Note that the first entry
1143 * of the wqueue array is always allocated so
1144 * that we always can remember how much was
1145 * written. */
1146 bus->wqueue[0] = sd_bus_message_ref(m);
1147 bus->wqueue_size = 1;
1148 bus->windex = idx;
1149 }
1150 } else {
1151 sd_bus_message **q;
1152
1153 /* Just append it to the queue. */
1154
25220239 1155 if (bus->wqueue_size >= BUS_WQUEUE_MAX)
de1c301e
LP
1156 return -ENOBUFS;
1157
1158 q = realloc(bus->wqueue, sizeof(sd_bus_message*) * (bus->wqueue_size + 1));
1159 if (!q)
1160 return -ENOMEM;
1161
1162 bus->wqueue = q;
1163 q[bus->wqueue_size ++] = sd_bus_message_ref(m);
1164 }
1165
1166 if (serial)
1167 *serial = BUS_MESSAGE_SERIAL(m);
1168
1169 return 0;
1170}
1171
1172static usec_t calc_elapse(uint64_t usec) {
1173 if (usec == (uint64_t) -1)
1174 return 0;
1175
1176 if (usec == 0)
e3017af9 1177 usec = BUS_DEFAULT_TIMEOUT;
de1c301e
LP
1178
1179 return now(CLOCK_MONOTONIC) + usec;
1180}
1181
e3017af9
LP
1182static int timeout_compare(const void *a, const void *b) {
1183 const struct reply_callback *x = a, *y = b;
1184
1185 if (x->timeout != 0 && y->timeout == 0)
1186 return -1;
1187
1188 if (x->timeout == 0 && y->timeout != 0)
1189 return 1;
1190
1191 if (x->timeout < y->timeout)
1192 return -1;
1193
1194 if (x->timeout > y->timeout)
1195 return 1;
1196
1197 return 0;
1198}
1199
de1c301e
LP
1200int sd_bus_send_with_reply(
1201 sd_bus *bus,
1202 sd_bus_message *m,
52f3ba91 1203 sd_bus_message_handler_t callback,
de1c301e
LP
1204 void *userdata,
1205 uint64_t usec,
1206 uint64_t *serial) {
1207
1208 struct reply_callback *c;
1209 int r;
1210
1211 if (!bus)
1212 return -EINVAL;
021a1e78
LP
1213 if (bus->state == BUS_UNSET)
1214 return -ENOTCONN;
e82c9509 1215 if (bus->output_fd < 0)
de1c301e
LP
1216 return -ENOTCONN;
1217 if (!m)
1218 return -EINVAL;
1219 if (!callback)
1220 return -EINVAL;
89ffcd2a 1221 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
de1c301e 1222 return -EINVAL;
89ffcd2a
LP
1223 if (m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
1224 return -EINVAL;
1225
1226 r = hashmap_ensure_allocated(&bus->reply_callbacks, uint64_hash_func, uint64_compare_func);
1227 if (r < 0)
1228 return r;
de1c301e 1229
e3017af9
LP
1230 if (usec != (uint64_t) -1) {
1231 r = prioq_ensure_allocated(&bus->reply_callbacks_prioq, timeout_compare);
1232 if (r < 0)
1233 return r;
1234 }
1235
de1c301e
LP
1236 r = bus_seal_message(bus, m);
1237 if (r < 0)
1238 return r;
1239
eba8617e 1240 c = new0(struct reply_callback, 1);
de1c301e
LP
1241 if (!c)
1242 return -ENOMEM;
1243
1244 c->callback = callback;
1245 c->userdata = userdata;
1246 c->serial = BUS_MESSAGE_SERIAL(m);
1247 c->timeout = calc_elapse(usec);
1248
1249 r = hashmap_put(bus->reply_callbacks, &c->serial, c);
1250 if (r < 0) {
1251 free(c);
1252 return r;
1253 }
1254
e3017af9
LP
1255 if (c->timeout != 0) {
1256 r = prioq_put(bus->reply_callbacks_prioq, c, &c->prioq_idx);
1257 if (r < 0) {
1258 c->timeout = 0;
1259 sd_bus_send_with_reply_cancel(bus, c->serial);
1260 return r;
1261 }
1262 }
1263
de1c301e
LP
1264 r = sd_bus_send(bus, m, serial);
1265 if (r < 0) {
e3017af9 1266 sd_bus_send_with_reply_cancel(bus, c->serial);
de1c301e
LP
1267 return r;
1268 }
1269
1270 return r;
1271}
1272
1273int sd_bus_send_with_reply_cancel(sd_bus *bus, uint64_t serial) {
e3017af9 1274 struct reply_callback *c;
de1c301e
LP
1275
1276 if (!bus)
1277 return -EINVAL;
1278 if (serial == 0)
1279 return -EINVAL;
1280
1281 c = hashmap_remove(bus->reply_callbacks, &serial);
1282 if (!c)
1283 return 0;
1284
e3017af9
LP
1285 if (c->timeout != 0)
1286 prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
1287
de1c301e
LP
1288 free(c);
1289 return 1;
1290}
1291
20902f3e 1292int bus_ensure_running(sd_bus *bus) {
89ffcd2a
LP
1293 int r;
1294
1295 assert(bus);
1296
e82c9509 1297 if (bus->input_fd < 0)
021a1e78
LP
1298 return -ENOTCONN;
1299 if (bus->state == BUS_UNSET)
1300 return -ENOTCONN;
1301
d728d708
LP
1302 if (bus->state == BUS_RUNNING)
1303 return 1;
89ffcd2a
LP
1304
1305 for (;;) {
1306 r = sd_bus_process(bus, NULL);
1307 if (r < 0)
1308 return r;
d728d708
LP
1309 if (bus->state == BUS_RUNNING)
1310 return 1;
e3017af9
LP
1311 if (r > 0)
1312 continue;
89ffcd2a
LP
1313
1314 r = sd_bus_wait(bus, (uint64_t) -1);
1315 if (r < 0)
1316 return r;
1317 }
1318}
1319
de1c301e
LP
1320int sd_bus_send_with_reply_and_block(
1321 sd_bus *bus,
1322 sd_bus_message *m,
1323 uint64_t usec,
1324 sd_bus_error *error,
1325 sd_bus_message **reply) {
1326
1327 int r;
1328 usec_t timeout;
1329 uint64_t serial;
1330 bool room = false;
1331
1332 if (!bus)
1333 return -EINVAL;
e82c9509 1334 if (bus->output_fd < 0)
de1c301e 1335 return -ENOTCONN;
021a1e78
LP
1336 if (bus->state == BUS_UNSET)
1337 return -ENOTCONN;
de1c301e
LP
1338 if (!m)
1339 return -EINVAL;
89ffcd2a 1340 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
de1c301e 1341 return -EINVAL;
89ffcd2a 1342 if (m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
de1c301e 1343 return -EINVAL;
89ffcd2a
LP
1344 if (bus_error_is_dirty(error))
1345 return -EINVAL;
1346
20902f3e 1347 r = bus_ensure_running(bus);
89ffcd2a
LP
1348 if (r < 0)
1349 return r;
de1c301e
LP
1350
1351 r = sd_bus_send(bus, m, &serial);
1352 if (r < 0)
1353 return r;
1354
1355 timeout = calc_elapse(usec);
1356
1357 for (;;) {
1358 usec_t left;
e3017af9 1359 sd_bus_message *incoming = NULL;
de1c301e
LP
1360
1361 if (!room) {
1362 sd_bus_message **q;
1363
25220239
LP
1364 if (bus->rqueue_size >= BUS_RQUEUE_MAX)
1365 return -ENOBUFS;
1366
de1c301e
LP
1367 /* Make sure there's room for queuing this
1368 * locally, before we read the message */
1369
1370 q = realloc(bus->rqueue, (bus->rqueue_size + 1) * sizeof(sd_bus_message*));
1371 if (!q)
1372 return -ENOMEM;
1373
1374 bus->rqueue = q;
1375 room = true;
1376 }
1377
6629161f
LP
1378 if (bus->is_kernel)
1379 r = bus_kernel_read_message(bus, &incoming);
1380 else
1381 r = bus_socket_read_message(bus, &incoming);
de1c301e
LP
1382 if (r < 0)
1383 return r;
e3017af9 1384 if (incoming) {
89ffcd2a 1385
de1c301e
LP
1386 if (incoming->reply_serial == serial) {
1387 /* Found a match! */
1388
1389 if (incoming->header->type == SD_BUS_MESSAGE_TYPE_METHOD_RETURN) {
b7f247e0
LP
1390
1391 if (reply)
1392 *reply = incoming;
1393 else
1394 sd_bus_message_unref(incoming);
1395
de1c301e
LP
1396 return 0;
1397 }
1398
1399 if (incoming->header->type == SD_BUS_MESSAGE_TYPE_METHOD_ERROR) {
1400 int k;
1401
1402 r = sd_bus_error_copy(error, &incoming->error);
1403 if (r < 0) {
1404 sd_bus_message_unref(incoming);
1405 return r;
1406 }
1407
1408 k = bus_error_to_errno(&incoming->error);
1409 sd_bus_message_unref(incoming);
1410 return k;
1411 }
1412
1413 sd_bus_message_unref(incoming);
1414 return -EIO;
1415 }
1416
1417 /* There's already guaranteed to be room for
1418 * this, so need to resize things here */
1419 bus->rqueue[bus->rqueue_size ++] = incoming;
1420 room = false;
1421
1422 /* Try to read more, right-away */
1423 continue;
1424 }
e3017af9
LP
1425 if (r != 0)
1426 continue;
de1c301e
LP
1427
1428 if (timeout > 0) {
1429 usec_t n;
1430
1431 n = now(CLOCK_MONOTONIC);
1432 if (n >= timeout)
1433 return -ETIMEDOUT;
1434
1435 left = timeout - n;
1436 } else
1437 left = (uint64_t) -1;
1438
e3017af9 1439 r = bus_poll(bus, true, left);
de1c301e
LP
1440 if (r < 0)
1441 return r;
1442
1443 r = dispatch_wqueue(bus);
1444 if (r < 0)
1445 return r;
1446 }
1447}
1448
1449int sd_bus_get_fd(sd_bus *bus) {
1450 if (!bus)
1451 return -EINVAL;
e82c9509 1452 if (bus->input_fd < 0)
89ffcd2a 1453 return -ENOTCONN;
e82c9509
LP
1454 if (bus->input_fd != bus->output_fd)
1455 return -EPERM;
de1c301e 1456
e82c9509 1457 return bus->input_fd;
de1c301e
LP
1458}
1459
1460int sd_bus_get_events(sd_bus *bus) {
1461 int flags = 0;
1462
1463 if (!bus)
1464 return -EINVAL;
021a1e78
LP
1465 if (bus->state == BUS_UNSET)
1466 return -ENOTCONN;
e82c9509 1467 if (bus->input_fd < 0)
89ffcd2a 1468 return -ENOTCONN;
de1c301e
LP
1469
1470 if (bus->state == BUS_OPENING)
1471 flags |= POLLOUT;
89ffcd2a
LP
1472 else if (bus->state == BUS_AUTHENTICATING) {
1473
2181a7f5 1474 if (bus_socket_auth_needs_write(bus))
89ffcd2a
LP
1475 flags |= POLLOUT;
1476
1477 flags |= POLLIN;
1478
1479 } else if (bus->state == BUS_RUNNING || bus->state == BUS_HELLO) {
de1c301e
LP
1480 if (bus->rqueue_size <= 0)
1481 flags |= POLLIN;
1482 if (bus->wqueue_size > 0)
1483 flags |= POLLOUT;
1484 }
1485
1486 return flags;
1487}
1488
e3017af9
LP
1489int sd_bus_get_timeout(sd_bus *bus, uint64_t *timeout_usec) {
1490 struct reply_callback *c;
1491
1492 if (!bus)
1493 return -EINVAL;
1494 if (!timeout_usec)
1495 return -EINVAL;
021a1e78
LP
1496 if (bus->state == BUS_UNSET)
1497 return -ENOTCONN;
e82c9509 1498 if (bus->input_fd < 0)
e3017af9
LP
1499 return -ENOTCONN;
1500
1501 if (bus->state == BUS_AUTHENTICATING) {
1502 *timeout_usec = bus->auth_timeout;
1503 return 1;
1504 }
1505
adee69fa
LP
1506 if (bus->state != BUS_RUNNING && bus->state != BUS_HELLO) {
1507 *timeout_usec = (uint64_t) -1;
e3017af9 1508 return 0;
adee69fa 1509 }
e3017af9
LP
1510
1511 c = prioq_peek(bus->reply_callbacks_prioq);
adee69fa
LP
1512 if (!c) {
1513 *timeout_usec = (uint64_t) -1;
e3017af9 1514 return 0;
adee69fa 1515 }
e3017af9
LP
1516
1517 *timeout_usec = c->timeout;
1518 return 1;
1519}
1520
1521static int process_timeout(sd_bus *bus) {
eb01ba5d 1522 _cleanup_bus_message_unref_ sd_bus_message* m = NULL;
e3017af9
LP
1523 struct reply_callback *c;
1524 usec_t n;
1525 int r;
1526
1527 assert(bus);
1528
1529 c = prioq_peek(bus->reply_callbacks_prioq);
1530 if (!c)
1531 return 0;
1532
1533 n = now(CLOCK_MONOTONIC);
1534 if (c->timeout > n)
1535 return 0;
1536
eb01ba5d
LP
1537 r = bus_message_new_synthetic_error(
1538 bus,
1539 c->serial,
1540 &SD_BUS_ERROR_MAKE("org.freedesktop.DBus.Error.Timeout", "Timed out"),
1541 &m);
1542 if (r < 0)
1543 return r;
1544
e3017af9
LP
1545 assert_se(prioq_pop(bus->reply_callbacks_prioq) == c);
1546 hashmap_remove(bus->reply_callbacks, &c->serial);
1547
eb01ba5d 1548 r = c->callback(bus, m, c->userdata);
e3017af9
LP
1549 free(c);
1550
1551 return r < 0 ? r : 1;
1552}
1553
9d373862
LP
1554static int process_hello(sd_bus *bus, sd_bus_message *m) {
1555 assert(bus);
1556 assert(m);
1557
1558 if (bus->state != BUS_HELLO)
1559 return 0;
1560
1561 /* Let's make sure the first message on the bus is the HELLO
1562 * reply. But note that we don't actually parse the message
2181a7f5
LP
1563 * here (we leave that to the usual handling), we just verify
1564 * we don't let any earlier msg through. */
9d373862
LP
1565
1566 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_RETURN &&
1567 m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_ERROR)
1568 return -EIO;
1569
1570 if (m->reply_serial != bus->hello_serial)
1571 return -EIO;
1572
1573 return 0;
1574}
1575
a652755d
LP
1576static int process_reply(sd_bus *bus, sd_bus_message *m) {
1577 struct reply_callback *c;
1578 int r;
1579
1580 assert(bus);
1581 assert(m);
1582
1583 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_RETURN &&
1584 m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_ERROR)
1585 return 0;
1586
1587 c = hashmap_remove(bus->reply_callbacks, &m->reply_serial);
1588 if (!c)
1589 return 0;
1590
1591 if (c->timeout != 0)
1592 prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
1593
88fe224c
LP
1594 r = sd_bus_message_rewind(m, true);
1595 if (r < 0)
1596 return r;
1597
eb01ba5d 1598 r = c->callback(bus, m, c->userdata);
a652755d
LP
1599 free(c);
1600
1601 return r;
1602}
1603
1604static int process_filter(sd_bus *bus, sd_bus_message *m) {
1605 struct filter_callback *l;
1606 int r;
1607
392d5b37
LP
1608 assert(bus);
1609 assert(m);
1610
7286037f
LP
1611 do {
1612 bus->filter_callbacks_modified = false;
1613
1614 LIST_FOREACH(callbacks, l, bus->filter_callbacks) {
1615
1616 if (bus->filter_callbacks_modified)
1617 break;
1618
1619 /* Don't run this more than once per iteration */
1620 if (l->last_iteration == bus->iteration_counter)
1621 continue;
1622
1623 l->last_iteration = bus->iteration_counter;
1624
88fe224c
LP
1625 r = sd_bus_message_rewind(m, true);
1626 if (r < 0)
1627 return r;
1628
eb01ba5d 1629 r = l->callback(bus, m, l->userdata);
7286037f
LP
1630 if (r != 0)
1631 return r;
1632
1633 }
1634
1635 } while (bus->filter_callbacks_modified);
a652755d
LP
1636
1637 return 0;
1638}
1639
392d5b37 1640static int process_match(sd_bus *bus, sd_bus_message *m) {
7286037f
LP
1641 int r;
1642
392d5b37
LP
1643 assert(bus);
1644 assert(m);
1645
7286037f
LP
1646 do {
1647 bus->match_callbacks_modified = false;
1648
eb01ba5d 1649 r = bus_match_run(bus, &bus->match_callbacks, m);
7286037f
LP
1650 if (r != 0)
1651 return r;
1652
1653 } while (bus->match_callbacks_modified);
1654
1655 return 0;
392d5b37
LP
1656}
1657
b9bf7e2b
LP
1658static int process_builtin(sd_bus *bus, sd_bus_message *m) {
1659 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1660 int r;
1661
1662 assert(bus);
1663 assert(m);
1664
1665 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
1666 return 0;
1667
1668 if (!streq_ptr(m->interface, "org.freedesktop.DBus.Peer"))
1669 return 0;
1670
1671 if (m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
1672 return 1;
1673
1674 if (streq_ptr(m->member, "Ping"))
1675 r = sd_bus_message_new_method_return(bus, m, &reply);
1676 else if (streq_ptr(m->member, "GetMachineId")) {
1677 sd_id128_t id;
1678 char sid[33];
1679
1680 r = sd_id128_get_machine(&id);
1681 if (r < 0)
1682 return r;
1683
1684 r = sd_bus_message_new_method_return(bus, m, &reply);
1685 if (r < 0)
1686 return r;
1687
1688 r = sd_bus_message_append(reply, "s", sd_id128_to_string(id, sid));
1689 } else {
c784c5ce 1690 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
b9bf7e2b
LP
1691
1692 sd_bus_error_set(&error,
1693 "org.freedesktop.DBus.Error.UnknownMethod",
1694 "Unknown method '%s' on interface '%s'.", m->member, m->interface);
1695
1696 r = sd_bus_message_new_method_error(bus, m, &error, &reply);
1697 }
1698
1699 if (r < 0)
1700 return r;
1701
1702 r = sd_bus_send(bus, reply, NULL);
1703 if (r < 0)
1704 return r;
1705
1706 return 1;
1707}
1708
a652755d 1709static int process_object(sd_bus *bus, sd_bus_message *m) {
c784c5ce 1710 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
a652755d
LP
1711 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1712 struct object_callback *c;
e3017af9 1713 int r;
a652755d 1714 bool found = false;
7286037f 1715 size_t pl;
e3017af9
LP
1716
1717 assert(bus);
1718 assert(m);
1719
a652755d
LP
1720 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
1721 return 0;
e3017af9 1722
a652755d
LP
1723 if (hashmap_isempty(bus->object_callbacks))
1724 return 0;
e3017af9 1725
7286037f 1726 pl = strlen(m->path);
a652755d 1727
7286037f
LP
1728 do {
1729 char p[pl+1];
e3017af9 1730
7286037f 1731 bus->object_callbacks_modified = false;
a652755d 1732
7286037f
LP
1733 c = hashmap_get(bus->object_callbacks, m->path);
1734 if (c && c->last_iteration != bus->iteration_counter) {
a652755d 1735
7286037f 1736 c->last_iteration = bus->iteration_counter;
a652755d 1737
88fe224c
LP
1738 r = sd_bus_message_rewind(m, true);
1739 if (r < 0)
1740 return r;
1741
eb01ba5d 1742 r = c->callback(bus, m, c->userdata);
e3017af9
LP
1743 if (r != 0)
1744 return r;
a652755d
LP
1745
1746 found = true;
e3017af9 1747 }
7286037f
LP
1748
1749 /* Look for fallback prefixes */
1750 strcpy(p, m->path);
1751 for (;;) {
1752 char *e;
1753
1754 if (bus->object_callbacks_modified)
1755 break;
1756
1757 e = strrchr(p, '/');
1758 if (e == p || !e)
1759 break;
1760
1761 *e = 0;
1762
1763 c = hashmap_get(bus->object_callbacks, p);
1764 if (c && c->last_iteration != bus->iteration_counter && c->is_fallback) {
1765
1766 c->last_iteration = bus->iteration_counter;
1767
88fe224c
LP
1768 r = sd_bus_message_rewind(m, true);
1769 if (r < 0)
1770 return r;
1771
eb01ba5d 1772 r = c->callback(bus, m, c->userdata);
7286037f
LP
1773 if (r != 0)
1774 return r;
1775
1776 found = true;
1777 }
1778 }
1779
1780 } while (bus->object_callbacks_modified);
e3017af9 1781
0a72c2bd
LP
1782 /* We found some handlers but none wanted to take this, then
1783 * return this -- with one exception, we can handle
1784 * introspection minimally ourselves */
1785 if (!found || sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect"))
a652755d
LP
1786 return 0;
1787
1788 sd_bus_error_set(&error,
1789 "org.freedesktop.DBus.Error.UnknownMethod",
1790 "Unknown method '%s' or interface '%s'.", m->member, m->interface);
1791
1792 r = sd_bus_message_new_method_error(bus, m, &error, &reply);
1793 if (r < 0)
1794 return r;
1795
1796 r = sd_bus_send(bus, reply, NULL);
1797 if (r < 0)
1798 return r;
e3017af9 1799
a652755d
LP
1800 return 1;
1801}
1802
0a72c2bd
LP
1803static int process_introspect(sd_bus *bus, sd_bus_message *m) {
1804 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1805 _cleanup_free_ char *introspection = NULL;
1806 _cleanup_set_free_free_ Set *s = NULL;
1807 _cleanup_fclose_ FILE *f = NULL;
1808 struct object_callback *c;
1809 Iterator i;
1810 size_t size = 0;
1811 char *node;
1812 int r;
1813
1814 assert(bus);
1815 assert(m);
1816
1817 if (!sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect"))
1818 return 0;
1819
1820 if (!m->path)
1821 return 0;
1822
1823 s = set_new(string_hash_func, string_compare_func);
1824 if (!s)
1825 return -ENOMEM;
1826
1827 HASHMAP_FOREACH(c, bus->object_callbacks, i) {
1828 const char *e;
1829 char *a, *p;
1830
1831 if (streq(c->path, "/"))
1832 continue;
1833
1834 if (streq(m->path, "/"))
1835 e = c->path;
1836 else {
1837 e = startswith(c->path, m->path);
1838 if (!e || *e != '/')
1839 continue;
1840 }
1841
1842 a = strdup(e+1);
1843 if (!a)
1844 return -ENOMEM;
1845
1846 p = strchr(a, '/');
1847 if (p)
1848 *p = 0;
1849
ef42202a
ZJS
1850 r = set_consume(s, a);
1851 if (r < 0 && r != -EEXIST)
1852 return r;
0a72c2bd
LP
1853 }
1854
1855 f = open_memstream(&introspection, &size);
1856 if (!f)
1857 return -ENOMEM;
1858
1859 fputs(SD_BUS_INTROSPECT_DOCTYPE, f);
1860 fputs("<node>\n", f);
1861 fputs(SD_BUS_INTROSPECT_INTERFACE_PEER, f);
1862 fputs(SD_BUS_INTROSPECT_INTERFACE_INTROSPECTABLE, f);
1863
1864 while ((node = set_steal_first(s))) {
1865 fprintf(f, " <node name=\"%s\"/>\n", node);
1866 free(node);
1867 }
1868
1869 fputs("</node>\n", f);
1870
1871 fflush(f);
1872
1873 if (ferror(f))
1874 return -ENOMEM;
1875
1876 r = sd_bus_message_new_method_return(bus, m, &reply);
1877 if (r < 0)
1878 return r;
1879
1880 r = sd_bus_message_append(reply, "s", introspection);
1881 if (r < 0)
1882 return r;
1883
1884 r = sd_bus_send(bus, reply, NULL);
1885 if (r < 0)
1886 return r;
1887
1888 return 1;
1889}
1890
a652755d
LP
1891static int process_message(sd_bus *bus, sd_bus_message *m) {
1892 int r;
1893
1894 assert(bus);
1895 assert(m);
1896
7286037f
LP
1897 bus->iteration_counter++;
1898
9d373862
LP
1899 r = process_hello(bus, m);
1900 if (r != 0)
1901 return r;
1902
a652755d
LP
1903 r = process_reply(bus, m);
1904 if (r != 0)
1905 return r;
1906
1907 r = process_filter(bus, m);
1908 if (r != 0)
1909 return r;
1910
392d5b37
LP
1911 r = process_match(bus, m);
1912 if (r != 0)
1913 return r;
1914
a652755d
LP
1915 r = process_builtin(bus, m);
1916 if (r != 0)
1917 return r;
1918
0a72c2bd
LP
1919 r = process_object(bus, m);
1920 if (r != 0)
1921 return r;
1922
1923 return process_introspect(bus, m);
e3017af9
LP
1924}
1925
a7e3212d
LP
1926static int process_running(sd_bus *bus, sd_bus_message **ret) {
1927 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
de1c301e
LP
1928 int r;
1929
a7e3212d
LP
1930 assert(bus);
1931 assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
de1c301e 1932
a7e3212d
LP
1933 r = process_timeout(bus);
1934 if (r != 0)
1935 goto null_message;
de1c301e 1936
a7e3212d
LP
1937 r = dispatch_wqueue(bus);
1938 if (r != 0)
1939 goto null_message;
de1c301e 1940
a7e3212d
LP
1941 r = dispatch_rqueue(bus, &m);
1942 if (r < 0)
1943 return r;
1944 if (!m)
1945 goto null_message;
de1c301e 1946
a7e3212d
LP
1947 r = process_message(bus, m);
1948 if (r != 0)
1949 goto null_message;
de1c301e 1950
a7e3212d 1951 if (ret) {
88fe224c
LP
1952 r = sd_bus_message_rewind(m, true);
1953 if (r < 0)
1954 return r;
1955
a7e3212d
LP
1956 *ret = m;
1957 m = NULL;
1958 return 1;
1959 }
de1c301e 1960
a7e3212d
LP
1961 if (m->header->type == SD_BUS_MESSAGE_TYPE_METHOD_CALL) {
1962 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
c784c5ce 1963 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
de1c301e 1964
a7e3212d 1965 sd_bus_error_set(&error, "org.freedesktop.DBus.Error.UnknownObject", "Unknown object '%s'.", m->path);
de1c301e 1966
a7e3212d
LP
1967 r = sd_bus_message_new_method_error(bus, m, &error, &reply);
1968 if (r < 0)
1969 return r;
de1c301e 1970
a7e3212d
LP
1971 r = sd_bus_send(bus, reply, NULL);
1972 if (r < 0)
1973 return r;
1974 }
e3017af9 1975
a7e3212d 1976 return 1;
de1c301e 1977
a7e3212d
LP
1978null_message:
1979 if (r >= 0 && ret)
1980 *ret = NULL;
de1c301e 1981
a7e3212d
LP
1982 return r;
1983}
e3017af9 1984
a7e3212d
LP
1985int sd_bus_process(sd_bus *bus, sd_bus_message **ret) {
1986 int r;
de1c301e 1987
a7e3212d
LP
1988 /* Returns 0 when we didn't do anything. This should cause the
1989 * caller to invoke sd_bus_wait() before returning the next
1990 * time. Returns > 0 when we did something, which possibly
1991 * means *ret is filled in with an unprocessed message. */
de1c301e 1992
a7e3212d
LP
1993 if (!bus)
1994 return -EINVAL;
e82c9509 1995 if (bus->input_fd < 0)
a7e3212d 1996 return -ENOTCONN;
de1c301e 1997
6807947e
LP
1998 /* We don't allow recursively invoking sd_bus_process(). */
1999 if (bus->processing)
2000 return -EBUSY;
2001
a7e3212d 2002 switch (bus->state) {
de1c301e 2003
a7e3212d
LP
2004 case BUS_UNSET:
2005 return -ENOTCONN;
de1c301e 2006
a7e3212d
LP
2007 case BUS_OPENING:
2008 r = bus_socket_process_opening(bus);
2009 if (r < 0)
2010 return r;
2011 if (ret)
2012 *ret = NULL;
2013 return r;
b9bf7e2b 2014
a7e3212d 2015 case BUS_AUTHENTICATING:
89ffcd2a 2016
a7e3212d
LP
2017 r = bus_socket_process_authenticating(bus);
2018 if (r < 0)
2019 return r;
2020 if (ret)
2021 *ret = NULL;
2022 return r;
89ffcd2a 2023
a7e3212d
LP
2024 case BUS_RUNNING:
2025 case BUS_HELLO:
89ffcd2a 2026
6807947e
LP
2027 bus->processing = true;
2028 r = process_running(bus, ret);
2029 bus->processing = false;
2030
2031 return r;
de1c301e
LP
2032 }
2033
89ffcd2a 2034 assert_not_reached("Unknown state");
de1c301e
LP
2035}
2036
e3017af9 2037static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec) {
b92bea5d 2038 struct pollfd p[2] = {};
e82c9509 2039 int r, e, n;
de1c301e 2040 struct timespec ts;
e3017af9
LP
2041 usec_t until, m;
2042
2043 assert(bus);
de1c301e 2044
e82c9509 2045 if (bus->input_fd < 0)
89ffcd2a
LP
2046 return -ENOTCONN;
2047
de1c301e
LP
2048 e = sd_bus_get_events(bus);
2049 if (e < 0)
2050 return e;
2051
e3017af9
LP
2052 if (need_more)
2053 e |= POLLIN;
2054
2055 r = sd_bus_get_timeout(bus, &until);
2056 if (r < 0)
2057 return r;
2058 if (r == 0)
2059 m = (uint64_t) -1;
2060 else {
e82c9509
LP
2061 usec_t nw;
2062 nw = now(CLOCK_MONOTONIC);
2063 m = until > nw ? until - nw : 0;
e3017af9
LP
2064 }
2065
2066 if (timeout_usec != (uint64_t) -1 && (m == (uint64_t) -1 || timeout_usec < m))
2067 m = timeout_usec;
2068
e82c9509 2069 p[0].fd = bus->input_fd;
e82c9509
LP
2070 if (bus->output_fd == bus->input_fd) {
2071 p[0].events = e;
2072 n = 1;
2073 } else {
2074 p[0].events = e & POLLIN;
2075 p[1].fd = bus->output_fd;
2076 p[1].events = e & POLLOUT;
2077 n = 2;
2078 }
de1c301e 2079
e82c9509 2080 r = ppoll(p, n, m == (uint64_t) -1 ? NULL : timespec_store(&ts, m), NULL);
de1c301e 2081 if (r < 0)
89ffcd2a 2082 return -errno;
de1c301e 2083
e3017af9
LP
2084 return r > 0 ? 1 : 0;
2085}
2086
2087int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec) {
2088
2089 if (!bus)
2090 return -EINVAL;
021a1e78
LP
2091 if (bus->state == BUS_UNSET)
2092 return -ENOTCONN;
e82c9509 2093 if (bus->input_fd < 0)
e3017af9
LP
2094 return -ENOTCONN;
2095 if (bus->rqueue_size > 0)
2096 return 0;
2097
2098 return bus_poll(bus, false, timeout_usec);
de1c301e
LP
2099}
2100
2101int sd_bus_flush(sd_bus *bus) {
2102 int r;
2103
2104 if (!bus)
2105 return -EINVAL;
021a1e78
LP
2106 if (bus->state == BUS_UNSET)
2107 return -ENOTCONN;
e82c9509 2108 if (bus->output_fd < 0)
de1c301e
LP
2109 return -ENOTCONN;
2110
20902f3e 2111 r = bus_ensure_running(bus);
89ffcd2a
LP
2112 if (r < 0)
2113 return r;
2114
2115 if (bus->wqueue_size <= 0)
de1c301e
LP
2116 return 0;
2117
2118 for (;;) {
2119 r = dispatch_wqueue(bus);
2120 if (r < 0)
2121 return r;
2122
89ffcd2a 2123 if (bus->wqueue_size <= 0)
de1c301e
LP
2124 return 0;
2125
e3017af9 2126 r = bus_poll(bus, false, (uint64_t) -1);
de1c301e
LP
2127 if (r < 0)
2128 return r;
2129 }
2130}
2131
52f3ba91 2132int sd_bus_add_filter(sd_bus *bus, sd_bus_message_handler_t callback, void *userdata) {
de1c301e
LP
2133 struct filter_callback *f;
2134
2135 if (!bus)
2136 return -EINVAL;
2137 if (!callback)
2138 return -EINVAL;
2139
eba8617e 2140 f = new0(struct filter_callback, 1);
de1c301e
LP
2141 if (!f)
2142 return -ENOMEM;
2143 f->callback = callback;
2144 f->userdata = userdata;
2145
7286037f 2146 bus->filter_callbacks_modified = true;
de1c301e
LP
2147 LIST_PREPEND(struct filter_callback, callbacks, bus->filter_callbacks, f);
2148 return 0;
2149}
2150
52f3ba91 2151int sd_bus_remove_filter(sd_bus *bus, sd_bus_message_handler_t callback, void *userdata) {
de1c301e
LP
2152 struct filter_callback *f;
2153
2154 if (!bus)
2155 return -EINVAL;
2156 if (!callback)
2157 return -EINVAL;
2158
2159 LIST_FOREACH(callbacks, f, bus->filter_callbacks) {
2160 if (f->callback == callback && f->userdata == userdata) {
7286037f 2161 bus->filter_callbacks_modified = true;
de1c301e
LP
2162 LIST_REMOVE(struct filter_callback, callbacks, bus->filter_callbacks, f);
2163 free(f);
2164 return 1;
2165 }
2166 }
2167
2168 return 0;
2169}
a652755d
LP
2170
2171static int bus_add_object(
2172 sd_bus *bus,
2173 bool fallback,
2174 const char *path,
52f3ba91 2175 sd_bus_message_handler_t callback,
a652755d
LP
2176 void *userdata) {
2177
2178 struct object_callback *c;
2179 int r;
2180
2181 if (!bus)
2182 return -EINVAL;
2183 if (!path)
2184 return -EINVAL;
2185 if (!callback)
2186 return -EINVAL;
2187
2188 r = hashmap_ensure_allocated(&bus->object_callbacks, string_hash_func, string_compare_func);
2189 if (r < 0)
2190 return r;
2191
eba8617e 2192 c = new0(struct object_callback, 1);
a652755d
LP
2193 if (!c)
2194 return -ENOMEM;
2195
2196 c->path = strdup(path);
531991b6 2197 if (!c->path) {
a652755d
LP
2198 free(c);
2199 return -ENOMEM;
2200 }
2201
2202 c->callback = callback;
2203 c->userdata = userdata;
2204 c->is_fallback = fallback;
2205
7286037f 2206 bus->object_callbacks_modified = true;
a652755d
LP
2207 r = hashmap_put(bus->object_callbacks, c->path, c);
2208 if (r < 0) {
2209 free(c->path);
2210 free(c);
2211 return r;
2212 }
2213
2214 return 0;
2215}
2216
2217static int bus_remove_object(
2218 sd_bus *bus,
2219 bool fallback,
2220 const char *path,
52f3ba91 2221 sd_bus_message_handler_t callback,
a652755d
LP
2222 void *userdata) {
2223
2224 struct object_callback *c;
2225
2226 if (!bus)
2227 return -EINVAL;
2228 if (!path)
2229 return -EINVAL;
2230 if (!callback)
2231 return -EINVAL;
2232
2233 c = hashmap_get(bus->object_callbacks, path);
2234 if (!c)
2235 return 0;
2236
2237 if (c->callback != callback || c->userdata != userdata || c->is_fallback != fallback)
2238 return 0;
2239
7286037f 2240 bus->object_callbacks_modified = true;
a652755d
LP
2241 assert_se(c == hashmap_remove(bus->object_callbacks, c->path));
2242
2243 free(c->path);
2244 free(c);
2245
2246 return 1;
2247}
2248
52f3ba91 2249int sd_bus_add_object(sd_bus *bus, const char *path, sd_bus_message_handler_t callback, void *userdata) {
a652755d
LP
2250 return bus_add_object(bus, false, path, callback, userdata);
2251}
2252
52f3ba91 2253int sd_bus_remove_object(sd_bus *bus, const char *path, sd_bus_message_handler_t callback, void *userdata) {
a652755d
LP
2254 return bus_remove_object(bus, false, path, callback, userdata);
2255}
2256
52f3ba91 2257int sd_bus_add_fallback(sd_bus *bus, const char *prefix, sd_bus_message_handler_t callback, void *userdata) {
a652755d
LP
2258 return bus_add_object(bus, true, prefix, callback, userdata);
2259}
2260
52f3ba91 2261int sd_bus_remove_fallback(sd_bus *bus, const char *prefix, sd_bus_message_handler_t callback, void *userdata) {
a652755d
LP
2262 return bus_remove_object(bus, true, prefix, callback, userdata);
2263}
392d5b37 2264
52f3ba91 2265int sd_bus_add_match(sd_bus *bus, const char *match, sd_bus_message_handler_t callback, void *userdata) {
392d5b37
LP
2266 int r = 0;
2267
2268 if (!bus)
2269 return -EINVAL;
2270 if (!match)
2271 return -EINVAL;
2272
2273 if (bus->bus_client) {
2274 r = bus_add_match_internal(bus, match);
2275 if (r < 0)
2276 return r;
2277 }
2278
2279 if (callback) {
7286037f 2280 bus->match_callbacks_modified = true;
392d5b37
LP
2281 r = bus_match_add(&bus->match_callbacks, match, callback, userdata, NULL);
2282 if (r < 0) {
2283
2284 if (bus->bus_client)
2285 bus_remove_match_internal(bus, match);
2286 }
2287 }
2288
2289 return r;
2290}
2291
52f3ba91 2292int sd_bus_remove_match(sd_bus *bus, const char *match, sd_bus_message_handler_t callback, void *userdata) {
392d5b37
LP
2293 int r = 0, q = 0;
2294
2295 if (!bus)
2296 return -EINVAL;
2297 if (!match)
2298 return -EINVAL;
2299
2300 if (bus->bus_client)
2301 r = bus_remove_match_internal(bus, match);
2302
7286037f
LP
2303 if (callback) {
2304 bus->match_callbacks_modified = true;
392d5b37 2305 q = bus_match_remove(&bus->match_callbacks, match, callback, userdata);
7286037f 2306 }
392d5b37
LP
2307
2308 if (r < 0)
2309 return r;
2310 return q;
2311}
917b5dc7
LP
2312
2313int sd_bus_emit_signal(
2314 sd_bus *bus,
2315 const char *path,
2316 const char *interface,
2317 const char *member,
2318 const char *types, ...) {
2319
2320 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2321 va_list ap;
2322 int r;
2323
2324 if (!bus)
2325 return -EINVAL;
2326
2327 r = sd_bus_message_new_signal(bus, path, interface, member, &m);
2328 if (r < 0)
2329 return r;
2330
2331 va_start(ap, types);
2332 r = bus_message_append_ap(m, types, ap);
2333 va_end(ap);
2334 if (r < 0)
2335 return r;
2336
2337 return sd_bus_send(bus, m, NULL);
2338}
2339
2340int sd_bus_call_method(
2341 sd_bus *bus,
2342 const char *destination,
2343 const char *path,
2344 const char *interface,
2345 const char *member,
2346 sd_bus_error *error,
2347 sd_bus_message **reply,
2348 const char *types, ...) {
2349
2350 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2351 va_list ap;
2352 int r;
2353
2354 if (!bus)
2355 return -EINVAL;
2356
2357 r = sd_bus_message_new_method_call(bus, destination, path, interface, member, &m);
2358 if (r < 0)
2359 return r;
2360
2361 va_start(ap, types);
2362 r = bus_message_append_ap(m, types, ap);
2363 va_end(ap);
2364 if (r < 0)
2365 return r;
2366
2367 return sd_bus_send_with_reply_and_block(bus, m, 0, error, reply);
2368}
f10dda3b
LP
2369
2370int sd_bus_reply_method_return(
2371 sd_bus *bus,
2372 sd_bus_message *call,
2373 const char *types, ...) {
2374
2375 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2376 va_list ap;
2377 int r;
2378
2379 if (!bus)
2380 return -EINVAL;
2381 if (!call)
2382 return -EINVAL;
2383 if (!call->sealed)
2384 return -EPERM;
2385 if (call->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
2386 return -EINVAL;
2387
2388 if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
2389 return 0;
2390
2391 r = sd_bus_message_new_method_return(bus, call, &m);
2392 if (r < 0)
2393 return r;
2394
2395 va_start(ap, types);
2396 r = bus_message_append_ap(m, types, ap);
2397 va_end(ap);
2398 if (r < 0)
2399 return r;
2400
2401 return sd_bus_send(bus, m, NULL);
2402}
2403
2404int sd_bus_reply_method_error(
2405 sd_bus *bus,
2406 sd_bus_message *call,
2407 const sd_bus_error *e) {
2408
2409 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2410 int r;
2411
2412 if (!bus)
2413 return -EINVAL;
2414 if (!call)
2415 return -EINVAL;
2416 if (!call->sealed)
2417 return -EPERM;
2418 if (call->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
2419 return -EINVAL;
2420 if (!sd_bus_error_is_set(e))
2421 return -EINVAL;
2422
2423 if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
2424 return 0;
2425
2426 r = sd_bus_message_new_method_error(bus, call, e, &m);
2427 if (r < 0)
2428 return r;
2429
2430 return sd_bus_send(bus, m, NULL);
2431}