]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-bus/sd-bus.c
bus: synthesize timeout message errors instead of returning error codes
[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
LP
105
106 r->n_ref = 1;
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
937 assert(bus->n_ref > 0);
938
939 bus->n_ref++;
940 return bus;
941}
942
943sd_bus *sd_bus_unref(sd_bus *bus) {
944 if (!bus)
945 return NULL;
946
947 assert(bus->n_ref > 0);
948 bus->n_ref--;
949
950 if (bus->n_ref <= 0)
951 bus_free(bus);
952
953 return NULL;
954}
955
e3017af9
LP
956int sd_bus_is_open(sd_bus *bus) {
957 if (!bus)
958 return -EINVAL;
959
e82c9509 960 return bus->state != BUS_UNSET && bus->input_fd >= 0;
e3017af9
LP
961}
962
d728d708
LP
963int sd_bus_can_send(sd_bus *bus, char type) {
964 int r;
965
de1c301e
LP
966 if (!bus)
967 return -EINVAL;
e82c9509 968 if (bus->output_fd < 0)
021a1e78 969 return -ENOTCONN;
de1c301e 970
d728d708 971 if (type == SD_BUS_TYPE_UNIX_FD) {
021a1e78
LP
972 if (!bus->negotiate_fds)
973 return 0;
974
20902f3e 975 r = bus_ensure_running(bus);
d728d708
LP
976 if (r < 0)
977 return r;
de1c301e 978
d728d708
LP
979 return bus->can_fds;
980 }
981
982 return bus_type_is_valid(type);
de1c301e
LP
983}
984
98178d39 985int sd_bus_get_server_id(sd_bus *bus, sd_id128_t *server_id) {
d728d708 986 int r;
de1c301e
LP
987
988 if (!bus)
989 return -EINVAL;
98178d39 990 if (!server_id)
d728d708 991 return -EINVAL;
de1c301e 992
20902f3e 993 r = bus_ensure_running(bus);
d728d708
LP
994 if (r < 0)
995 return r;
de1c301e 996
98178d39 997 *server_id = bus->server_id;
d728d708 998 return 0;
de1c301e
LP
999}
1000
1001static int bus_seal_message(sd_bus *b, sd_bus_message *m) {
1002 assert(m);
1003
89ffcd2a
LP
1004 if (m->header->version > b->message_version)
1005 return -EPERM;
1006
de1c301e
LP
1007 if (m->sealed)
1008 return 0;
1009
9a17484d 1010 return bus_message_seal(m, ++b->serial);
de1c301e
LP
1011}
1012
de1c301e 1013static int dispatch_wqueue(sd_bus *bus) {
e3017af9 1014 int r, ret = 0;
de1c301e
LP
1015
1016 assert(bus);
89ffcd2a 1017 assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
de1c301e 1018
e82c9509 1019 if (bus->output_fd < 0)
de1c301e
LP
1020 return -ENOTCONN;
1021
1022 while (bus->wqueue_size > 0) {
1023
6629161f
LP
1024 if (bus->is_kernel)
1025 r = bus_kernel_write_message(bus, bus->wqueue[0]);
1026 else
1027 r = bus_socket_write_message(bus, bus->wqueue[0], &bus->windex);
1028
de1c301e
LP
1029 if (r < 0) {
1030 sd_bus_close(bus);
1031 return r;
1032 } else if (r == 0)
e3017af9
LP
1033 /* Didn't do anything this time */
1034 return ret;
6629161f 1035 else if (bus->is_kernel || bus->windex >= BUS_MESSAGE_SIZE(bus->wqueue[0])) {
de1c301e
LP
1036 /* Fully written. Let's drop the entry from
1037 * the queue.
1038 *
1039 * This isn't particularly optimized, but
1040 * well, this is supposed to be our worst-case
1041 * buffer only, and the socket buffer is
1042 * supposed to be our primary buffer, and if
1043 * it got full, then all bets are off
1044 * anyway. */
1045
1046 sd_bus_message_unref(bus->wqueue[0]);
1047 bus->wqueue_size --;
1048 memmove(bus->wqueue, bus->wqueue + 1, sizeof(sd_bus_message*) * bus->wqueue_size);
1049 bus->windex = 0;
1050
e3017af9 1051 ret = 1;
de1c301e
LP
1052 }
1053 }
1054
e3017af9 1055 return ret;
de1c301e
LP
1056}
1057
1058static int dispatch_rqueue(sd_bus *bus, sd_bus_message **m) {
2bf938c1 1059 sd_bus_message *z = NULL;
e3017af9 1060 int r, ret = 0;
de1c301e
LP
1061
1062 assert(bus);
1063 assert(m);
89ffcd2a 1064 assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
de1c301e 1065
e82c9509 1066 if (bus->input_fd < 0)
de1c301e
LP
1067 return -ENOTCONN;
1068
1069 if (bus->rqueue_size > 0) {
1070 /* Dispatch a queued message */
1071
1072 *m = bus->rqueue[0];
1073 bus->rqueue_size --;
1074 memmove(bus->rqueue, bus->rqueue + 1, sizeof(sd_bus_message*) * bus->rqueue_size);
1075 return 1;
1076 }
1077
1078 /* Try to read a new message */
e3017af9 1079 do {
6629161f
LP
1080 if (bus->is_kernel)
1081 r = bus_kernel_read_message(bus, &z);
1082 else
1083 r = bus_socket_read_message(bus, &z);
1084
e3017af9
LP
1085 if (r < 0) {
1086 sd_bus_close(bus);
1087 return r;
1088 }
1089 if (r == 0)
1090 return ret;
de1c301e 1091
e3017af9
LP
1092 r = 1;
1093 } while (!z);
1094
1095 *m = z;
1096 return 1;
de1c301e
LP
1097}
1098
1099int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *serial) {
1100 int r;
1101
1102 if (!bus)
1103 return -EINVAL;
021a1e78
LP
1104 if (bus->state == BUS_UNSET)
1105 return -ENOTCONN;
e82c9509 1106 if (bus->output_fd < 0)
de1c301e
LP
1107 return -ENOTCONN;
1108 if (!m)
1109 return -EINVAL;
021a1e78
LP
1110
1111 if (m->n_fds > 0) {
1112 r = sd_bus_can_send(bus, SD_BUS_TYPE_UNIX_FD);
1113 if (r < 0)
1114 return r;
1115 if (r == 0)
1116 return -ENOTSUP;
1117 }
de1c301e 1118
29f6aadd
LP
1119 /* If the serial number isn't kept, then we know that no reply
1120 * is expected */
1121 if (!serial && !m->sealed)
1122 m->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
1123
de1c301e
LP
1124 r = bus_seal_message(bus, m);
1125 if (r < 0)
1126 return r;
1127
5407f2de
LP
1128 /* If this is a reply and no reply was requested, then let's
1129 * suppress this, if we can */
1130 if (m->dont_send && !serial)
1131 return 0;
1132
89ffcd2a 1133 if ((bus->state == BUS_RUNNING || bus->state == BUS_HELLO) && bus->wqueue_size <= 0) {
de1c301e
LP
1134 size_t idx = 0;
1135
6629161f
LP
1136 if (bus->is_kernel)
1137 r = bus_kernel_write_message(bus, m);
1138 else
1139 r = bus_socket_write_message(bus, m, &idx);
1140
de1c301e
LP
1141 if (r < 0) {
1142 sd_bus_close(bus);
1143 return r;
6629161f 1144 } else if (!bus->is_kernel && idx < BUS_MESSAGE_SIZE(m)) {
de1c301e
LP
1145 /* Wasn't fully written. So let's remember how
1146 * much was written. Note that the first entry
1147 * of the wqueue array is always allocated so
1148 * that we always can remember how much was
1149 * written. */
1150 bus->wqueue[0] = sd_bus_message_ref(m);
1151 bus->wqueue_size = 1;
1152 bus->windex = idx;
1153 }
1154 } else {
1155 sd_bus_message **q;
1156
1157 /* Just append it to the queue. */
1158
25220239 1159 if (bus->wqueue_size >= BUS_WQUEUE_MAX)
de1c301e
LP
1160 return -ENOBUFS;
1161
1162 q = realloc(bus->wqueue, sizeof(sd_bus_message*) * (bus->wqueue_size + 1));
1163 if (!q)
1164 return -ENOMEM;
1165
1166 bus->wqueue = q;
1167 q[bus->wqueue_size ++] = sd_bus_message_ref(m);
1168 }
1169
1170 if (serial)
1171 *serial = BUS_MESSAGE_SERIAL(m);
1172
1173 return 0;
1174}
1175
1176static usec_t calc_elapse(uint64_t usec) {
1177 if (usec == (uint64_t) -1)
1178 return 0;
1179
1180 if (usec == 0)
e3017af9 1181 usec = BUS_DEFAULT_TIMEOUT;
de1c301e
LP
1182
1183 return now(CLOCK_MONOTONIC) + usec;
1184}
1185
e3017af9
LP
1186static int timeout_compare(const void *a, const void *b) {
1187 const struct reply_callback *x = a, *y = b;
1188
1189 if (x->timeout != 0 && y->timeout == 0)
1190 return -1;
1191
1192 if (x->timeout == 0 && y->timeout != 0)
1193 return 1;
1194
1195 if (x->timeout < y->timeout)
1196 return -1;
1197
1198 if (x->timeout > y->timeout)
1199 return 1;
1200
1201 return 0;
1202}
1203
de1c301e
LP
1204int sd_bus_send_with_reply(
1205 sd_bus *bus,
1206 sd_bus_message *m,
52f3ba91 1207 sd_bus_message_handler_t callback,
de1c301e
LP
1208 void *userdata,
1209 uint64_t usec,
1210 uint64_t *serial) {
1211
1212 struct reply_callback *c;
1213 int r;
1214
1215 if (!bus)
1216 return -EINVAL;
021a1e78
LP
1217 if (bus->state == BUS_UNSET)
1218 return -ENOTCONN;
e82c9509 1219 if (bus->output_fd < 0)
de1c301e
LP
1220 return -ENOTCONN;
1221 if (!m)
1222 return -EINVAL;
1223 if (!callback)
1224 return -EINVAL;
89ffcd2a 1225 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
de1c301e 1226 return -EINVAL;
89ffcd2a
LP
1227 if (m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
1228 return -EINVAL;
1229
1230 r = hashmap_ensure_allocated(&bus->reply_callbacks, uint64_hash_func, uint64_compare_func);
1231 if (r < 0)
1232 return r;
de1c301e 1233
e3017af9
LP
1234 if (usec != (uint64_t) -1) {
1235 r = prioq_ensure_allocated(&bus->reply_callbacks_prioq, timeout_compare);
1236 if (r < 0)
1237 return r;
1238 }
1239
de1c301e
LP
1240 r = bus_seal_message(bus, m);
1241 if (r < 0)
1242 return r;
1243
eba8617e 1244 c = new0(struct reply_callback, 1);
de1c301e
LP
1245 if (!c)
1246 return -ENOMEM;
1247
1248 c->callback = callback;
1249 c->userdata = userdata;
1250 c->serial = BUS_MESSAGE_SERIAL(m);
1251 c->timeout = calc_elapse(usec);
1252
1253 r = hashmap_put(bus->reply_callbacks, &c->serial, c);
1254 if (r < 0) {
1255 free(c);
1256 return r;
1257 }
1258
e3017af9
LP
1259 if (c->timeout != 0) {
1260 r = prioq_put(bus->reply_callbacks_prioq, c, &c->prioq_idx);
1261 if (r < 0) {
1262 c->timeout = 0;
1263 sd_bus_send_with_reply_cancel(bus, c->serial);
1264 return r;
1265 }
1266 }
1267
de1c301e
LP
1268 r = sd_bus_send(bus, m, serial);
1269 if (r < 0) {
e3017af9 1270 sd_bus_send_with_reply_cancel(bus, c->serial);
de1c301e
LP
1271 return r;
1272 }
1273
1274 return r;
1275}
1276
1277int sd_bus_send_with_reply_cancel(sd_bus *bus, uint64_t serial) {
e3017af9 1278 struct reply_callback *c;
de1c301e
LP
1279
1280 if (!bus)
1281 return -EINVAL;
1282 if (serial == 0)
1283 return -EINVAL;
1284
1285 c = hashmap_remove(bus->reply_callbacks, &serial);
1286 if (!c)
1287 return 0;
1288
e3017af9
LP
1289 if (c->timeout != 0)
1290 prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
1291
de1c301e
LP
1292 free(c);
1293 return 1;
1294}
1295
20902f3e 1296int bus_ensure_running(sd_bus *bus) {
89ffcd2a
LP
1297 int r;
1298
1299 assert(bus);
1300
e82c9509 1301 if (bus->input_fd < 0)
021a1e78
LP
1302 return -ENOTCONN;
1303 if (bus->state == BUS_UNSET)
1304 return -ENOTCONN;
1305
d728d708
LP
1306 if (bus->state == BUS_RUNNING)
1307 return 1;
89ffcd2a
LP
1308
1309 for (;;) {
1310 r = sd_bus_process(bus, NULL);
1311 if (r < 0)
1312 return r;
d728d708
LP
1313 if (bus->state == BUS_RUNNING)
1314 return 1;
e3017af9
LP
1315 if (r > 0)
1316 continue;
89ffcd2a
LP
1317
1318 r = sd_bus_wait(bus, (uint64_t) -1);
1319 if (r < 0)
1320 return r;
1321 }
1322}
1323
de1c301e
LP
1324int sd_bus_send_with_reply_and_block(
1325 sd_bus *bus,
1326 sd_bus_message *m,
1327 uint64_t usec,
1328 sd_bus_error *error,
1329 sd_bus_message **reply) {
1330
1331 int r;
1332 usec_t timeout;
1333 uint64_t serial;
1334 bool room = false;
1335
1336 if (!bus)
1337 return -EINVAL;
e82c9509 1338 if (bus->output_fd < 0)
de1c301e 1339 return -ENOTCONN;
021a1e78
LP
1340 if (bus->state == BUS_UNSET)
1341 return -ENOTCONN;
de1c301e
LP
1342 if (!m)
1343 return -EINVAL;
89ffcd2a 1344 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
de1c301e 1345 return -EINVAL;
89ffcd2a 1346 if (m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
de1c301e 1347 return -EINVAL;
89ffcd2a
LP
1348 if (bus_error_is_dirty(error))
1349 return -EINVAL;
1350
20902f3e 1351 r = bus_ensure_running(bus);
89ffcd2a
LP
1352 if (r < 0)
1353 return r;
de1c301e
LP
1354
1355 r = sd_bus_send(bus, m, &serial);
1356 if (r < 0)
1357 return r;
1358
1359 timeout = calc_elapse(usec);
1360
1361 for (;;) {
1362 usec_t left;
e3017af9 1363 sd_bus_message *incoming = NULL;
de1c301e
LP
1364
1365 if (!room) {
1366 sd_bus_message **q;
1367
25220239
LP
1368 if (bus->rqueue_size >= BUS_RQUEUE_MAX)
1369 return -ENOBUFS;
1370
de1c301e
LP
1371 /* Make sure there's room for queuing this
1372 * locally, before we read the message */
1373
1374 q = realloc(bus->rqueue, (bus->rqueue_size + 1) * sizeof(sd_bus_message*));
1375 if (!q)
1376 return -ENOMEM;
1377
1378 bus->rqueue = q;
1379 room = true;
1380 }
1381
6629161f
LP
1382 if (bus->is_kernel)
1383 r = bus_kernel_read_message(bus, &incoming);
1384 else
1385 r = bus_socket_read_message(bus, &incoming);
de1c301e
LP
1386 if (r < 0)
1387 return r;
e3017af9 1388 if (incoming) {
89ffcd2a 1389
de1c301e
LP
1390 if (incoming->reply_serial == serial) {
1391 /* Found a match! */
1392
1393 if (incoming->header->type == SD_BUS_MESSAGE_TYPE_METHOD_RETURN) {
b7f247e0
LP
1394
1395 if (reply)
1396 *reply = incoming;
1397 else
1398 sd_bus_message_unref(incoming);
1399
de1c301e
LP
1400 return 0;
1401 }
1402
1403 if (incoming->header->type == SD_BUS_MESSAGE_TYPE_METHOD_ERROR) {
1404 int k;
1405
1406 r = sd_bus_error_copy(error, &incoming->error);
1407 if (r < 0) {
1408 sd_bus_message_unref(incoming);
1409 return r;
1410 }
1411
1412 k = bus_error_to_errno(&incoming->error);
1413 sd_bus_message_unref(incoming);
1414 return k;
1415 }
1416
1417 sd_bus_message_unref(incoming);
1418 return -EIO;
1419 }
1420
1421 /* There's already guaranteed to be room for
1422 * this, so need to resize things here */
1423 bus->rqueue[bus->rqueue_size ++] = incoming;
1424 room = false;
1425
1426 /* Try to read more, right-away */
1427 continue;
1428 }
e3017af9
LP
1429 if (r != 0)
1430 continue;
de1c301e
LP
1431
1432 if (timeout > 0) {
1433 usec_t n;
1434
1435 n = now(CLOCK_MONOTONIC);
1436 if (n >= timeout)
1437 return -ETIMEDOUT;
1438
1439 left = timeout - n;
1440 } else
1441 left = (uint64_t) -1;
1442
e3017af9 1443 r = bus_poll(bus, true, left);
de1c301e
LP
1444 if (r < 0)
1445 return r;
1446
1447 r = dispatch_wqueue(bus);
1448 if (r < 0)
1449 return r;
1450 }
1451}
1452
1453int sd_bus_get_fd(sd_bus *bus) {
1454 if (!bus)
1455 return -EINVAL;
e82c9509 1456 if (bus->input_fd < 0)
89ffcd2a 1457 return -ENOTCONN;
e82c9509
LP
1458 if (bus->input_fd != bus->output_fd)
1459 return -EPERM;
de1c301e 1460
e82c9509 1461 return bus->input_fd;
de1c301e
LP
1462}
1463
1464int sd_bus_get_events(sd_bus *bus) {
1465 int flags = 0;
1466
1467 if (!bus)
1468 return -EINVAL;
021a1e78
LP
1469 if (bus->state == BUS_UNSET)
1470 return -ENOTCONN;
e82c9509 1471 if (bus->input_fd < 0)
89ffcd2a 1472 return -ENOTCONN;
de1c301e
LP
1473
1474 if (bus->state == BUS_OPENING)
1475 flags |= POLLOUT;
89ffcd2a
LP
1476 else if (bus->state == BUS_AUTHENTICATING) {
1477
2181a7f5 1478 if (bus_socket_auth_needs_write(bus))
89ffcd2a
LP
1479 flags |= POLLOUT;
1480
1481 flags |= POLLIN;
1482
1483 } else if (bus->state == BUS_RUNNING || bus->state == BUS_HELLO) {
de1c301e
LP
1484 if (bus->rqueue_size <= 0)
1485 flags |= POLLIN;
1486 if (bus->wqueue_size > 0)
1487 flags |= POLLOUT;
1488 }
1489
1490 return flags;
1491}
1492
e3017af9
LP
1493int sd_bus_get_timeout(sd_bus *bus, uint64_t *timeout_usec) {
1494 struct reply_callback *c;
1495
1496 if (!bus)
1497 return -EINVAL;
1498 if (!timeout_usec)
1499 return -EINVAL;
021a1e78
LP
1500 if (bus->state == BUS_UNSET)
1501 return -ENOTCONN;
e82c9509 1502 if (bus->input_fd < 0)
e3017af9
LP
1503 return -ENOTCONN;
1504
1505 if (bus->state == BUS_AUTHENTICATING) {
1506 *timeout_usec = bus->auth_timeout;
1507 return 1;
1508 }
1509
adee69fa
LP
1510 if (bus->state != BUS_RUNNING && bus->state != BUS_HELLO) {
1511 *timeout_usec = (uint64_t) -1;
e3017af9 1512 return 0;
adee69fa 1513 }
e3017af9
LP
1514
1515 c = prioq_peek(bus->reply_callbacks_prioq);
adee69fa
LP
1516 if (!c) {
1517 *timeout_usec = (uint64_t) -1;
e3017af9 1518 return 0;
adee69fa 1519 }
e3017af9
LP
1520
1521 *timeout_usec = c->timeout;
1522 return 1;
1523}
1524
1525static int process_timeout(sd_bus *bus) {
eb01ba5d 1526 _cleanup_bus_message_unref_ sd_bus_message* m = NULL;
e3017af9
LP
1527 struct reply_callback *c;
1528 usec_t n;
1529 int r;
1530
1531 assert(bus);
1532
1533 c = prioq_peek(bus->reply_callbacks_prioq);
1534 if (!c)
1535 return 0;
1536
1537 n = now(CLOCK_MONOTONIC);
1538 if (c->timeout > n)
1539 return 0;
1540
eb01ba5d
LP
1541 r = bus_message_new_synthetic_error(
1542 bus,
1543 c->serial,
1544 &SD_BUS_ERROR_MAKE("org.freedesktop.DBus.Error.Timeout", "Timed out"),
1545 &m);
1546 if (r < 0)
1547 return r;
1548
e3017af9
LP
1549 assert_se(prioq_pop(bus->reply_callbacks_prioq) == c);
1550 hashmap_remove(bus->reply_callbacks, &c->serial);
1551
eb01ba5d 1552 r = c->callback(bus, m, c->userdata);
e3017af9
LP
1553 free(c);
1554
1555 return r < 0 ? r : 1;
1556}
1557
9d373862
LP
1558static int process_hello(sd_bus *bus, sd_bus_message *m) {
1559 assert(bus);
1560 assert(m);
1561
1562 if (bus->state != BUS_HELLO)
1563 return 0;
1564
1565 /* Let's make sure the first message on the bus is the HELLO
1566 * reply. But note that we don't actually parse the message
2181a7f5
LP
1567 * here (we leave that to the usual handling), we just verify
1568 * we don't let any earlier msg through. */
9d373862
LP
1569
1570 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_RETURN &&
1571 m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_ERROR)
1572 return -EIO;
1573
1574 if (m->reply_serial != bus->hello_serial)
1575 return -EIO;
1576
1577 return 0;
1578}
1579
a652755d
LP
1580static int process_reply(sd_bus *bus, sd_bus_message *m) {
1581 struct reply_callback *c;
1582 int r;
1583
1584 assert(bus);
1585 assert(m);
1586
1587 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_RETURN &&
1588 m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_ERROR)
1589 return 0;
1590
1591 c = hashmap_remove(bus->reply_callbacks, &m->reply_serial);
1592 if (!c)
1593 return 0;
1594
1595 if (c->timeout != 0)
1596 prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
1597
88fe224c
LP
1598 r = sd_bus_message_rewind(m, true);
1599 if (r < 0)
1600 return r;
1601
eb01ba5d 1602 r = c->callback(bus, m, c->userdata);
a652755d
LP
1603 free(c);
1604
1605 return r;
1606}
1607
1608static int process_filter(sd_bus *bus, sd_bus_message *m) {
1609 struct filter_callback *l;
1610 int r;
1611
392d5b37
LP
1612 assert(bus);
1613 assert(m);
1614
7286037f
LP
1615 do {
1616 bus->filter_callbacks_modified = false;
1617
1618 LIST_FOREACH(callbacks, l, bus->filter_callbacks) {
1619
1620 if (bus->filter_callbacks_modified)
1621 break;
1622
1623 /* Don't run this more than once per iteration */
1624 if (l->last_iteration == bus->iteration_counter)
1625 continue;
1626
1627 l->last_iteration = bus->iteration_counter;
1628
88fe224c
LP
1629 r = sd_bus_message_rewind(m, true);
1630 if (r < 0)
1631 return r;
1632
eb01ba5d 1633 r = l->callback(bus, m, l->userdata);
7286037f
LP
1634 if (r != 0)
1635 return r;
1636
1637 }
1638
1639 } while (bus->filter_callbacks_modified);
a652755d
LP
1640
1641 return 0;
1642}
1643
392d5b37 1644static int process_match(sd_bus *bus, sd_bus_message *m) {
7286037f
LP
1645 int r;
1646
392d5b37
LP
1647 assert(bus);
1648 assert(m);
1649
7286037f
LP
1650 do {
1651 bus->match_callbacks_modified = false;
1652
eb01ba5d 1653 r = bus_match_run(bus, &bus->match_callbacks, m);
7286037f
LP
1654 if (r != 0)
1655 return r;
1656
1657 } while (bus->match_callbacks_modified);
1658
1659 return 0;
392d5b37
LP
1660}
1661
b9bf7e2b
LP
1662static int process_builtin(sd_bus *bus, sd_bus_message *m) {
1663 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1664 int r;
1665
1666 assert(bus);
1667 assert(m);
1668
1669 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
1670 return 0;
1671
1672 if (!streq_ptr(m->interface, "org.freedesktop.DBus.Peer"))
1673 return 0;
1674
1675 if (m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
1676 return 1;
1677
1678 if (streq_ptr(m->member, "Ping"))
1679 r = sd_bus_message_new_method_return(bus, m, &reply);
1680 else if (streq_ptr(m->member, "GetMachineId")) {
1681 sd_id128_t id;
1682 char sid[33];
1683
1684 r = sd_id128_get_machine(&id);
1685 if (r < 0)
1686 return r;
1687
1688 r = sd_bus_message_new_method_return(bus, m, &reply);
1689 if (r < 0)
1690 return r;
1691
1692 r = sd_bus_message_append(reply, "s", sd_id128_to_string(id, sid));
1693 } else {
c784c5ce 1694 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
b9bf7e2b
LP
1695
1696 sd_bus_error_set(&error,
1697 "org.freedesktop.DBus.Error.UnknownMethod",
1698 "Unknown method '%s' on interface '%s'.", m->member, m->interface);
1699
1700 r = sd_bus_message_new_method_error(bus, m, &error, &reply);
1701 }
1702
1703 if (r < 0)
1704 return r;
1705
1706 r = sd_bus_send(bus, reply, NULL);
1707 if (r < 0)
1708 return r;
1709
1710 return 1;
1711}
1712
a652755d 1713static int process_object(sd_bus *bus, sd_bus_message *m) {
c784c5ce 1714 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
a652755d
LP
1715 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1716 struct object_callback *c;
e3017af9 1717 int r;
a652755d 1718 bool found = false;
7286037f 1719 size_t pl;
e3017af9
LP
1720
1721 assert(bus);
1722 assert(m);
1723
a652755d
LP
1724 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
1725 return 0;
e3017af9 1726
a652755d
LP
1727 if (hashmap_isempty(bus->object_callbacks))
1728 return 0;
e3017af9 1729
7286037f 1730 pl = strlen(m->path);
a652755d 1731
7286037f
LP
1732 do {
1733 char p[pl+1];
e3017af9 1734
7286037f 1735 bus->object_callbacks_modified = false;
a652755d 1736
7286037f
LP
1737 c = hashmap_get(bus->object_callbacks, m->path);
1738 if (c && c->last_iteration != bus->iteration_counter) {
a652755d 1739
7286037f 1740 c->last_iteration = bus->iteration_counter;
a652755d 1741
88fe224c
LP
1742 r = sd_bus_message_rewind(m, true);
1743 if (r < 0)
1744 return r;
1745
eb01ba5d 1746 r = c->callback(bus, m, c->userdata);
e3017af9
LP
1747 if (r != 0)
1748 return r;
a652755d
LP
1749
1750 found = true;
e3017af9 1751 }
7286037f
LP
1752
1753 /* Look for fallback prefixes */
1754 strcpy(p, m->path);
1755 for (;;) {
1756 char *e;
1757
1758 if (bus->object_callbacks_modified)
1759 break;
1760
1761 e = strrchr(p, '/');
1762 if (e == p || !e)
1763 break;
1764
1765 *e = 0;
1766
1767 c = hashmap_get(bus->object_callbacks, p);
1768 if (c && c->last_iteration != bus->iteration_counter && c->is_fallback) {
1769
1770 c->last_iteration = bus->iteration_counter;
1771
88fe224c
LP
1772 r = sd_bus_message_rewind(m, true);
1773 if (r < 0)
1774 return r;
1775
eb01ba5d 1776 r = c->callback(bus, m, c->userdata);
7286037f
LP
1777 if (r != 0)
1778 return r;
1779
1780 found = true;
1781 }
1782 }
1783
1784 } while (bus->object_callbacks_modified);
e3017af9 1785
0a72c2bd
LP
1786 /* We found some handlers but none wanted to take this, then
1787 * return this -- with one exception, we can handle
1788 * introspection minimally ourselves */
1789 if (!found || sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect"))
a652755d
LP
1790 return 0;
1791
1792 sd_bus_error_set(&error,
1793 "org.freedesktop.DBus.Error.UnknownMethod",
1794 "Unknown method '%s' or interface '%s'.", m->member, m->interface);
1795
1796 r = sd_bus_message_new_method_error(bus, m, &error, &reply);
1797 if (r < 0)
1798 return r;
1799
1800 r = sd_bus_send(bus, reply, NULL);
1801 if (r < 0)
1802 return r;
e3017af9 1803
a652755d
LP
1804 return 1;
1805}
1806
0a72c2bd
LP
1807static int process_introspect(sd_bus *bus, sd_bus_message *m) {
1808 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1809 _cleanup_free_ char *introspection = NULL;
1810 _cleanup_set_free_free_ Set *s = NULL;
1811 _cleanup_fclose_ FILE *f = NULL;
1812 struct object_callback *c;
1813 Iterator i;
1814 size_t size = 0;
1815 char *node;
1816 int r;
1817
1818 assert(bus);
1819 assert(m);
1820
1821 if (!sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect"))
1822 return 0;
1823
1824 if (!m->path)
1825 return 0;
1826
1827 s = set_new(string_hash_func, string_compare_func);
1828 if (!s)
1829 return -ENOMEM;
1830
1831 HASHMAP_FOREACH(c, bus->object_callbacks, i) {
1832 const char *e;
1833 char *a, *p;
1834
1835 if (streq(c->path, "/"))
1836 continue;
1837
1838 if (streq(m->path, "/"))
1839 e = c->path;
1840 else {
1841 e = startswith(c->path, m->path);
1842 if (!e || *e != '/')
1843 continue;
1844 }
1845
1846 a = strdup(e+1);
1847 if (!a)
1848 return -ENOMEM;
1849
1850 p = strchr(a, '/');
1851 if (p)
1852 *p = 0;
1853
ef42202a
ZJS
1854 r = set_consume(s, a);
1855 if (r < 0 && r != -EEXIST)
1856 return r;
0a72c2bd
LP
1857 }
1858
1859 f = open_memstream(&introspection, &size);
1860 if (!f)
1861 return -ENOMEM;
1862
1863 fputs(SD_BUS_INTROSPECT_DOCTYPE, f);
1864 fputs("<node>\n", f);
1865 fputs(SD_BUS_INTROSPECT_INTERFACE_PEER, f);
1866 fputs(SD_BUS_INTROSPECT_INTERFACE_INTROSPECTABLE, f);
1867
1868 while ((node = set_steal_first(s))) {
1869 fprintf(f, " <node name=\"%s\"/>\n", node);
1870 free(node);
1871 }
1872
1873 fputs("</node>\n", f);
1874
1875 fflush(f);
1876
1877 if (ferror(f))
1878 return -ENOMEM;
1879
1880 r = sd_bus_message_new_method_return(bus, m, &reply);
1881 if (r < 0)
1882 return r;
1883
1884 r = sd_bus_message_append(reply, "s", introspection);
1885 if (r < 0)
1886 return r;
1887
1888 r = sd_bus_send(bus, reply, NULL);
1889 if (r < 0)
1890 return r;
1891
1892 return 1;
1893}
1894
a652755d
LP
1895static int process_message(sd_bus *bus, sd_bus_message *m) {
1896 int r;
1897
1898 assert(bus);
1899 assert(m);
1900
7286037f
LP
1901 bus->iteration_counter++;
1902
9d373862
LP
1903 r = process_hello(bus, m);
1904 if (r != 0)
1905 return r;
1906
a652755d
LP
1907 r = process_reply(bus, m);
1908 if (r != 0)
1909 return r;
1910
1911 r = process_filter(bus, m);
1912 if (r != 0)
1913 return r;
1914
392d5b37
LP
1915 r = process_match(bus, m);
1916 if (r != 0)
1917 return r;
1918
a652755d
LP
1919 r = process_builtin(bus, m);
1920 if (r != 0)
1921 return r;
1922
0a72c2bd
LP
1923 r = process_object(bus, m);
1924 if (r != 0)
1925 return r;
1926
1927 return process_introspect(bus, m);
e3017af9
LP
1928}
1929
a7e3212d
LP
1930static int process_running(sd_bus *bus, sd_bus_message **ret) {
1931 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
de1c301e
LP
1932 int r;
1933
a7e3212d
LP
1934 assert(bus);
1935 assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
de1c301e 1936
a7e3212d
LP
1937 r = process_timeout(bus);
1938 if (r != 0)
1939 goto null_message;
de1c301e 1940
a7e3212d
LP
1941 r = dispatch_wqueue(bus);
1942 if (r != 0)
1943 goto null_message;
de1c301e 1944
a7e3212d
LP
1945 r = dispatch_rqueue(bus, &m);
1946 if (r < 0)
1947 return r;
1948 if (!m)
1949 goto null_message;
de1c301e 1950
a7e3212d
LP
1951 r = process_message(bus, m);
1952 if (r != 0)
1953 goto null_message;
de1c301e 1954
a7e3212d 1955 if (ret) {
88fe224c
LP
1956 r = sd_bus_message_rewind(m, true);
1957 if (r < 0)
1958 return r;
1959
a7e3212d
LP
1960 *ret = m;
1961 m = NULL;
1962 return 1;
1963 }
de1c301e 1964
a7e3212d
LP
1965 if (m->header->type == SD_BUS_MESSAGE_TYPE_METHOD_CALL) {
1966 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
c784c5ce 1967 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
de1c301e 1968
a7e3212d 1969 sd_bus_error_set(&error, "org.freedesktop.DBus.Error.UnknownObject", "Unknown object '%s'.", m->path);
de1c301e 1970
a7e3212d
LP
1971 r = sd_bus_message_new_method_error(bus, m, &error, &reply);
1972 if (r < 0)
1973 return r;
de1c301e 1974
a7e3212d
LP
1975 r = sd_bus_send(bus, reply, NULL);
1976 if (r < 0)
1977 return r;
1978 }
e3017af9 1979
a7e3212d 1980 return 1;
de1c301e 1981
a7e3212d
LP
1982null_message:
1983 if (r >= 0 && ret)
1984 *ret = NULL;
de1c301e 1985
a7e3212d
LP
1986 return r;
1987}
e3017af9 1988
a7e3212d
LP
1989int sd_bus_process(sd_bus *bus, sd_bus_message **ret) {
1990 int r;
de1c301e 1991
a7e3212d
LP
1992 /* Returns 0 when we didn't do anything. This should cause the
1993 * caller to invoke sd_bus_wait() before returning the next
1994 * time. Returns > 0 when we did something, which possibly
1995 * means *ret is filled in with an unprocessed message. */
de1c301e 1996
a7e3212d
LP
1997 if (!bus)
1998 return -EINVAL;
e82c9509 1999 if (bus->input_fd < 0)
a7e3212d 2000 return -ENOTCONN;
de1c301e 2001
6807947e
LP
2002 /* We don't allow recursively invoking sd_bus_process(). */
2003 if (bus->processing)
2004 return -EBUSY;
2005
a7e3212d 2006 switch (bus->state) {
de1c301e 2007
a7e3212d
LP
2008 case BUS_UNSET:
2009 return -ENOTCONN;
de1c301e 2010
a7e3212d
LP
2011 case BUS_OPENING:
2012 r = bus_socket_process_opening(bus);
2013 if (r < 0)
2014 return r;
2015 if (ret)
2016 *ret = NULL;
2017 return r;
b9bf7e2b 2018
a7e3212d 2019 case BUS_AUTHENTICATING:
89ffcd2a 2020
a7e3212d
LP
2021 r = bus_socket_process_authenticating(bus);
2022 if (r < 0)
2023 return r;
2024 if (ret)
2025 *ret = NULL;
2026 return r;
89ffcd2a 2027
a7e3212d
LP
2028 case BUS_RUNNING:
2029 case BUS_HELLO:
89ffcd2a 2030
6807947e
LP
2031 bus->processing = true;
2032 r = process_running(bus, ret);
2033 bus->processing = false;
2034
2035 return r;
de1c301e
LP
2036 }
2037
89ffcd2a 2038 assert_not_reached("Unknown state");
de1c301e
LP
2039}
2040
e3017af9 2041static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec) {
b92bea5d 2042 struct pollfd p[2] = {};
e82c9509 2043 int r, e, n;
de1c301e 2044 struct timespec ts;
e3017af9
LP
2045 usec_t until, m;
2046
2047 assert(bus);
de1c301e 2048
e82c9509 2049 if (bus->input_fd < 0)
89ffcd2a
LP
2050 return -ENOTCONN;
2051
de1c301e
LP
2052 e = sd_bus_get_events(bus);
2053 if (e < 0)
2054 return e;
2055
e3017af9
LP
2056 if (need_more)
2057 e |= POLLIN;
2058
2059 r = sd_bus_get_timeout(bus, &until);
2060 if (r < 0)
2061 return r;
2062 if (r == 0)
2063 m = (uint64_t) -1;
2064 else {
e82c9509
LP
2065 usec_t nw;
2066 nw = now(CLOCK_MONOTONIC);
2067 m = until > nw ? until - nw : 0;
e3017af9
LP
2068 }
2069
2070 if (timeout_usec != (uint64_t) -1 && (m == (uint64_t) -1 || timeout_usec < m))
2071 m = timeout_usec;
2072
e82c9509 2073 p[0].fd = bus->input_fd;
e82c9509
LP
2074 if (bus->output_fd == bus->input_fd) {
2075 p[0].events = e;
2076 n = 1;
2077 } else {
2078 p[0].events = e & POLLIN;
2079 p[1].fd = bus->output_fd;
2080 p[1].events = e & POLLOUT;
2081 n = 2;
2082 }
de1c301e 2083
e82c9509 2084 r = ppoll(p, n, m == (uint64_t) -1 ? NULL : timespec_store(&ts, m), NULL);
de1c301e 2085 if (r < 0)
89ffcd2a 2086 return -errno;
de1c301e 2087
e3017af9
LP
2088 return r > 0 ? 1 : 0;
2089}
2090
2091int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec) {
2092
2093 if (!bus)
2094 return -EINVAL;
021a1e78
LP
2095 if (bus->state == BUS_UNSET)
2096 return -ENOTCONN;
e82c9509 2097 if (bus->input_fd < 0)
e3017af9
LP
2098 return -ENOTCONN;
2099 if (bus->rqueue_size > 0)
2100 return 0;
2101
2102 return bus_poll(bus, false, timeout_usec);
de1c301e
LP
2103}
2104
2105int sd_bus_flush(sd_bus *bus) {
2106 int r;
2107
2108 if (!bus)
2109 return -EINVAL;
021a1e78
LP
2110 if (bus->state == BUS_UNSET)
2111 return -ENOTCONN;
e82c9509 2112 if (bus->output_fd < 0)
de1c301e
LP
2113 return -ENOTCONN;
2114
20902f3e 2115 r = bus_ensure_running(bus);
89ffcd2a
LP
2116 if (r < 0)
2117 return r;
2118
2119 if (bus->wqueue_size <= 0)
de1c301e
LP
2120 return 0;
2121
2122 for (;;) {
2123 r = dispatch_wqueue(bus);
2124 if (r < 0)
2125 return r;
2126
89ffcd2a 2127 if (bus->wqueue_size <= 0)
de1c301e
LP
2128 return 0;
2129
e3017af9 2130 r = bus_poll(bus, false, (uint64_t) -1);
de1c301e
LP
2131 if (r < 0)
2132 return r;
2133 }
2134}
2135
52f3ba91 2136int sd_bus_add_filter(sd_bus *bus, sd_bus_message_handler_t callback, void *userdata) {
de1c301e
LP
2137 struct filter_callback *f;
2138
2139 if (!bus)
2140 return -EINVAL;
2141 if (!callback)
2142 return -EINVAL;
2143
eba8617e 2144 f = new0(struct filter_callback, 1);
de1c301e
LP
2145 if (!f)
2146 return -ENOMEM;
2147 f->callback = callback;
2148 f->userdata = userdata;
2149
7286037f 2150 bus->filter_callbacks_modified = true;
de1c301e
LP
2151 LIST_PREPEND(struct filter_callback, callbacks, bus->filter_callbacks, f);
2152 return 0;
2153}
2154
52f3ba91 2155int sd_bus_remove_filter(sd_bus *bus, sd_bus_message_handler_t callback, void *userdata) {
de1c301e
LP
2156 struct filter_callback *f;
2157
2158 if (!bus)
2159 return -EINVAL;
2160 if (!callback)
2161 return -EINVAL;
2162
2163 LIST_FOREACH(callbacks, f, bus->filter_callbacks) {
2164 if (f->callback == callback && f->userdata == userdata) {
7286037f 2165 bus->filter_callbacks_modified = true;
de1c301e
LP
2166 LIST_REMOVE(struct filter_callback, callbacks, bus->filter_callbacks, f);
2167 free(f);
2168 return 1;
2169 }
2170 }
2171
2172 return 0;
2173}
a652755d
LP
2174
2175static int bus_add_object(
2176 sd_bus *bus,
2177 bool fallback,
2178 const char *path,
52f3ba91 2179 sd_bus_message_handler_t callback,
a652755d
LP
2180 void *userdata) {
2181
2182 struct object_callback *c;
2183 int r;
2184
2185 if (!bus)
2186 return -EINVAL;
2187 if (!path)
2188 return -EINVAL;
2189 if (!callback)
2190 return -EINVAL;
2191
2192 r = hashmap_ensure_allocated(&bus->object_callbacks, string_hash_func, string_compare_func);
2193 if (r < 0)
2194 return r;
2195
eba8617e 2196 c = new0(struct object_callback, 1);
a652755d
LP
2197 if (!c)
2198 return -ENOMEM;
2199
2200 c->path = strdup(path);
531991b6 2201 if (!c->path) {
a652755d
LP
2202 free(c);
2203 return -ENOMEM;
2204 }
2205
2206 c->callback = callback;
2207 c->userdata = userdata;
2208 c->is_fallback = fallback;
2209
7286037f 2210 bus->object_callbacks_modified = true;
a652755d
LP
2211 r = hashmap_put(bus->object_callbacks, c->path, c);
2212 if (r < 0) {
2213 free(c->path);
2214 free(c);
2215 return r;
2216 }
2217
2218 return 0;
2219}
2220
2221static int bus_remove_object(
2222 sd_bus *bus,
2223 bool fallback,
2224 const char *path,
52f3ba91 2225 sd_bus_message_handler_t callback,
a652755d
LP
2226 void *userdata) {
2227
2228 struct object_callback *c;
2229
2230 if (!bus)
2231 return -EINVAL;
2232 if (!path)
2233 return -EINVAL;
2234 if (!callback)
2235 return -EINVAL;
2236
2237 c = hashmap_get(bus->object_callbacks, path);
2238 if (!c)
2239 return 0;
2240
2241 if (c->callback != callback || c->userdata != userdata || c->is_fallback != fallback)
2242 return 0;
2243
7286037f 2244 bus->object_callbacks_modified = true;
a652755d
LP
2245 assert_se(c == hashmap_remove(bus->object_callbacks, c->path));
2246
2247 free(c->path);
2248 free(c);
2249
2250 return 1;
2251}
2252
52f3ba91 2253int sd_bus_add_object(sd_bus *bus, const char *path, sd_bus_message_handler_t callback, void *userdata) {
a652755d
LP
2254 return bus_add_object(bus, false, path, callback, userdata);
2255}
2256
52f3ba91 2257int sd_bus_remove_object(sd_bus *bus, const char *path, sd_bus_message_handler_t callback, void *userdata) {
a652755d
LP
2258 return bus_remove_object(bus, false, path, callback, userdata);
2259}
2260
52f3ba91 2261int sd_bus_add_fallback(sd_bus *bus, const char *prefix, sd_bus_message_handler_t callback, void *userdata) {
a652755d
LP
2262 return bus_add_object(bus, true, prefix, callback, userdata);
2263}
2264
52f3ba91 2265int sd_bus_remove_fallback(sd_bus *bus, const char *prefix, sd_bus_message_handler_t callback, void *userdata) {
a652755d
LP
2266 return bus_remove_object(bus, true, prefix, callback, userdata);
2267}
392d5b37 2268
52f3ba91 2269int sd_bus_add_match(sd_bus *bus, const char *match, sd_bus_message_handler_t callback, void *userdata) {
392d5b37
LP
2270 int r = 0;
2271
2272 if (!bus)
2273 return -EINVAL;
2274 if (!match)
2275 return -EINVAL;
2276
2277 if (bus->bus_client) {
2278 r = bus_add_match_internal(bus, match);
2279 if (r < 0)
2280 return r;
2281 }
2282
2283 if (callback) {
7286037f 2284 bus->match_callbacks_modified = true;
392d5b37
LP
2285 r = bus_match_add(&bus->match_callbacks, match, callback, userdata, NULL);
2286 if (r < 0) {
2287
2288 if (bus->bus_client)
2289 bus_remove_match_internal(bus, match);
2290 }
2291 }
2292
2293 return r;
2294}
2295
52f3ba91 2296int sd_bus_remove_match(sd_bus *bus, const char *match, sd_bus_message_handler_t callback, void *userdata) {
392d5b37
LP
2297 int r = 0, q = 0;
2298
2299 if (!bus)
2300 return -EINVAL;
2301 if (!match)
2302 return -EINVAL;
2303
2304 if (bus->bus_client)
2305 r = bus_remove_match_internal(bus, match);
2306
7286037f
LP
2307 if (callback) {
2308 bus->match_callbacks_modified = true;
392d5b37 2309 q = bus_match_remove(&bus->match_callbacks, match, callback, userdata);
7286037f 2310 }
392d5b37
LP
2311
2312 if (r < 0)
2313 return r;
2314 return q;
2315}
917b5dc7
LP
2316
2317int sd_bus_emit_signal(
2318 sd_bus *bus,
2319 const char *path,
2320 const char *interface,
2321 const char *member,
2322 const char *types, ...) {
2323
2324 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2325 va_list ap;
2326 int r;
2327
2328 if (!bus)
2329 return -EINVAL;
2330
2331 r = sd_bus_message_new_signal(bus, path, interface, member, &m);
2332 if (r < 0)
2333 return r;
2334
2335 va_start(ap, types);
2336 r = bus_message_append_ap(m, types, ap);
2337 va_end(ap);
2338 if (r < 0)
2339 return r;
2340
2341 return sd_bus_send(bus, m, NULL);
2342}
2343
2344int sd_bus_call_method(
2345 sd_bus *bus,
2346 const char *destination,
2347 const char *path,
2348 const char *interface,
2349 const char *member,
2350 sd_bus_error *error,
2351 sd_bus_message **reply,
2352 const char *types, ...) {
2353
2354 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2355 va_list ap;
2356 int r;
2357
2358 if (!bus)
2359 return -EINVAL;
2360
2361 r = sd_bus_message_new_method_call(bus, destination, path, interface, member, &m);
2362 if (r < 0)
2363 return r;
2364
2365 va_start(ap, types);
2366 r = bus_message_append_ap(m, types, ap);
2367 va_end(ap);
2368 if (r < 0)
2369 return r;
2370
2371 return sd_bus_send_with_reply_and_block(bus, m, 0, error, reply);
2372}
f10dda3b
LP
2373
2374int sd_bus_reply_method_return(
2375 sd_bus *bus,
2376 sd_bus_message *call,
2377 const char *types, ...) {
2378
2379 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2380 va_list ap;
2381 int r;
2382
2383 if (!bus)
2384 return -EINVAL;
2385 if (!call)
2386 return -EINVAL;
2387 if (!call->sealed)
2388 return -EPERM;
2389 if (call->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
2390 return -EINVAL;
2391
2392 if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
2393 return 0;
2394
2395 r = sd_bus_message_new_method_return(bus, call, &m);
2396 if (r < 0)
2397 return r;
2398
2399 va_start(ap, types);
2400 r = bus_message_append_ap(m, types, ap);
2401 va_end(ap);
2402 if (r < 0)
2403 return r;
2404
2405 return sd_bus_send(bus, m, NULL);
2406}
2407
2408int sd_bus_reply_method_error(
2409 sd_bus *bus,
2410 sd_bus_message *call,
2411 const sd_bus_error *e) {
2412
2413 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2414 int r;
2415
2416 if (!bus)
2417 return -EINVAL;
2418 if (!call)
2419 return -EINVAL;
2420 if (!call->sealed)
2421 return -EPERM;
2422 if (call->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
2423 return -EINVAL;
2424 if (!sd_bus_error_is_set(e))
2425 return -EINVAL;
2426
2427 if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
2428 return 0;
2429
2430 r = sd_bus_message_new_method_error(bus, call, e, &m);
2431 if (r < 0)
2432 return r;
2433
2434 return sd_bus_send(bus, m, NULL);
2435}