]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-bus/sd-bus.c
bus: actually unmap kdbus pool after use
[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>
63edf05e 29#include <sys/mman.h>
de1c301e
LP
30
31#include "util.h"
32#include "macro.h"
2fd9ae2e 33#include "strv.h"
0a72c2bd 34#include "set.h"
6c03089c 35#include "missing.h"
de1c301e
LP
36
37#include "sd-bus.h"
38#include "bus-internal.h"
39#include "bus-message.h"
40#include "bus-type.h"
a7e3212d 41#include "bus-socket.h"
6629161f 42#include "bus-kernel.h"
392d5b37 43#include "bus-control.h"
de1c301e 44
e3017af9
LP
45static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec);
46
f54514f3
LP
47static void bus_close_fds(sd_bus *b) {
48 assert(b);
49
50 if (b->input_fd >= 0)
51 close_nointr_nofail(b->input_fd);
52
53 if (b->output_fd >= 0 && b->output_fd != b->input_fd)
54 close_nointr_nofail(b->output_fd);
55
56 b->input_fd = b->output_fd = -1;
57}
58
de1c301e
LP
59static void bus_free(sd_bus *b) {
60 struct filter_callback *f;
a652755d 61 struct object_callback *c;
89ffcd2a 62 unsigned i;
de1c301e
LP
63
64 assert(b);
65
f54514f3 66 bus_close_fds(b);
de1c301e 67
63edf05e
LP
68 if (b->kdbus_buffer)
69 munmap(b->kdbus_buffer, KDBUS_POOL_SIZE);
70
de1c301e 71 free(b->rbuffer);
89ffcd2a 72 free(b->unique_name);
2181a7f5 73 free(b->auth_buffer);
89ffcd2a 74 free(b->address);
e9a967f9 75 free(b->kernel);
89ffcd2a 76
2fd9ae2e
LP
77 free(b->exec_path);
78 strv_free(b->exec_argv);
79
2c93b4ef
LP
80 close_many(b->fds, b->n_fds);
81 free(b->fds);
82
89ffcd2a
LP
83 for (i = 0; i < b->rqueue_size; i++)
84 sd_bus_message_unref(b->rqueue[i]);
de1c301e 85 free(b->rqueue);
89ffcd2a
LP
86
87 for (i = 0; i < b->wqueue_size; i++)
88 sd_bus_message_unref(b->wqueue[i]);
de1c301e 89 free(b->wqueue);
de1c301e
LP
90
91 hashmap_free_free(b->reply_callbacks);
e3017af9 92 prioq_free(b->reply_callbacks_prioq);
de1c301e
LP
93
94 while ((f = b->filter_callbacks)) {
95 LIST_REMOVE(struct filter_callback, callbacks, b->filter_callbacks, f);
96 free(f);
97 }
98
a652755d
LP
99 while ((c = hashmap_steal_first(b->object_callbacks))) {
100 free(c->path);
101 free(c);
102 }
103
104 hashmap_free(b->object_callbacks);
392d5b37
LP
105 bus_match_free(&b->match_callbacks);
106
bc7fd8cd
LP
107 bus_kernel_flush_memfd(b);
108
de1c301e
LP
109 free(b);
110}
111
021a1e78 112int sd_bus_new(sd_bus **ret) {
de1c301e
LP
113 sd_bus *r;
114
021a1e78
LP
115 if (!ret)
116 return -EINVAL;
117
de1c301e
LP
118 r = new0(sd_bus, 1);
119 if (!r)
021a1e78 120 return -ENOMEM;
de1c301e 121
e4ee6e5c 122 r->n_ref = REFCNT_INIT;
e82c9509 123 r->input_fd = r->output_fd = -1;
de1c301e 124 r->message_version = 1;
021a1e78 125 r->negotiate_fds = true;
de1c301e
LP
126
127 /* We guarantee that wqueue always has space for at least one
128 * entry */
129 r->wqueue = new(sd_bus_message*, 1);
130 if (!r->wqueue) {
131 free(r);
021a1e78 132 return -ENOMEM;
de1c301e
LP
133 }
134
021a1e78
LP
135 *ret = r;
136 return 0;
137}
138
139int sd_bus_set_address(sd_bus *bus, const char *address) {
140 char *a;
141
142 if (!bus)
143 return -EINVAL;
144 if (bus->state != BUS_UNSET)
145 return -EPERM;
146 if (!address)
147 return -EINVAL;
148
149 a = strdup(address);
150 if (!a)
151 return -ENOMEM;
152
153 free(bus->address);
154 bus->address = a;
155
156 return 0;
157}
158
e82c9509 159int sd_bus_set_fd(sd_bus *bus, int input_fd, int output_fd) {
021a1e78
LP
160 if (!bus)
161 return -EINVAL;
162 if (bus->state != BUS_UNSET)
163 return -EPERM;
e82c9509
LP
164 if (input_fd < 0)
165 return -EINVAL;
166 if (output_fd < 0)
021a1e78
LP
167 return -EINVAL;
168
e82c9509
LP
169 bus->input_fd = input_fd;
170 bus->output_fd = output_fd;
021a1e78
LP
171 return 0;
172}
173
2fd9ae2e
LP
174int sd_bus_set_exec(sd_bus *bus, const char *path, char *const argv[]) {
175 char *p, **a;
176
177 if (!bus)
178 return -EINVAL;
179 if (bus->state != BUS_UNSET)
180 return -EPERM;
181 if (!path)
182 return -EINVAL;
183 if (strv_isempty(argv))
184 return -EINVAL;
185
186 p = strdup(path);
187 if (!p)
188 return -ENOMEM;
189
190 a = strv_copy(argv);
191 if (!a) {
192 free(p);
193 return -ENOMEM;
194 }
195
196 free(bus->exec_path);
197 strv_free(bus->exec_argv);
198
199 bus->exec_path = p;
200 bus->exec_argv = a;
201
202 return 0;
203}
204
94bbf1ba 205int sd_bus_set_bus_client(sd_bus *bus, int b) {
021a1e78
LP
206 if (!bus)
207 return -EINVAL;
208 if (bus->state != BUS_UNSET)
209 return -EPERM;
210
94bbf1ba 211 bus->bus_client = !!b;
021a1e78
LP
212 return 0;
213}
214
215int sd_bus_set_negotiate_fds(sd_bus *bus, int b) {
216 if (!bus)
217 return -EINVAL;
218 if (bus->state != BUS_UNSET)
219 return -EPERM;
220
221 bus->negotiate_fds = !!b;
222 return 0;
223}
de1c301e 224
98178d39 225int sd_bus_set_server(sd_bus *bus, int b, sd_id128_t server_id) {
2181a7f5
LP
226 if (!bus)
227 return -EINVAL;
98178d39 228 if (!b && !sd_id128_equal(server_id, SD_ID128_NULL))
2181a7f5
LP
229 return -EINVAL;
230 if (bus->state != BUS_UNSET)
231 return -EPERM;
232
233 bus->is_server = !!b;
98178d39 234 bus->server_id = server_id;
2181a7f5
LP
235 return 0;
236}
237
238int sd_bus_set_anonymous(sd_bus *bus, int b) {
239 if (!bus)
240 return -EINVAL;
241 if (bus->state != BUS_UNSET)
242 return -EPERM;
243
244 bus->anonymous_auth = !!b;
245 return 0;
246}
247
eb01ba5d 248static int hello_callback(sd_bus *bus, sd_bus_message *reply, void *userdata) {
de1c301e
LP
249 const char *s;
250 int r;
251
252 assert(bus);
021a1e78 253 assert(bus->state == BUS_HELLO);
de1c301e
LP
254 assert(reply);
255
eb01ba5d
LP
256 r = bus_message_to_errno(reply);
257 if (r < 0)
258 return r;
259
de1c301e
LP
260 r = sd_bus_message_read(reply, "s", &s);
261 if (r < 0)
262 return r;
263
dafb7591
LP
264 if (!service_name_is_valid(s) || s[0] != ':')
265 return -EBADMSG;
266
de1c301e
LP
267 bus->unique_name = strdup(s);
268 if (!bus->unique_name)
269 return -ENOMEM;
270
dafb7591
LP
271 bus->state = BUS_RUNNING;
272
de1c301e
LP
273 return 1;
274}
275
276static int bus_send_hello(sd_bus *bus) {
277 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
278 int r;
279
280 assert(bus);
281
6629161f 282 if (!bus->bus_client || bus->is_kernel)
021a1e78
LP
283 return 0;
284
de1c301e
LP
285 r = sd_bus_message_new_method_call(
286 bus,
287 "org.freedesktop.DBus",
288 "/",
289 "org.freedesktop.DBus",
290 "Hello",
291 &m);
292 if (r < 0)
293 return r;
294
9d373862 295 return sd_bus_send_with_reply(bus, m, hello_callback, NULL, 0, &bus->hello_serial);
de1c301e
LP
296}
297
a7e3212d 298int bus_start_running(sd_bus *bus) {
de1c301e
LP
299 assert(bus);
300
f08838da 301 if (bus->bus_client && !bus->is_kernel) {
de1c301e 302 bus->state = BUS_HELLO;
e3017af9 303 return 1;
de1c301e
LP
304 }
305
306 bus->state = BUS_RUNNING;
e3017af9 307 return 1;
de1c301e
LP
308}
309
310static int parse_address_key(const char **p, const char *key, char **value) {
311 size_t l, n = 0;
312 const char *a;
313 char *r = NULL;
314
315 assert(p);
316 assert(*p);
de1c301e
LP
317 assert(value);
318
2fd9ae2e
LP
319 if (key) {
320 l = strlen(key);
321 if (strncmp(*p, key, l) != 0)
322 return 0;
de1c301e 323
2fd9ae2e
LP
324 if ((*p)[l] != '=')
325 return 0;
de1c301e 326
2fd9ae2e
LP
327 if (*value)
328 return -EINVAL;
de1c301e 329
2fd9ae2e
LP
330 a = *p + l + 1;
331 } else
332 a = *p;
333
334 while (*a != ';' && *a != ',' && *a != 0) {
de1c301e
LP
335 char c, *t;
336
337 if (*a == '%') {
338 int x, y;
339
340 x = unhexchar(a[1]);
341 if (x < 0) {
342 free(r);
343 return x;
344 }
345
346 y = unhexchar(a[2]);
347 if (y < 0) {
348 free(r);
349 return y;
350 }
351
de1c301e 352 c = (char) ((x << 4) | y);
89ffcd2a
LP
353 a += 3;
354 } else {
de1c301e 355 c = *a;
89ffcd2a
LP
356 a++;
357 }
de1c301e 358
89ffcd2a 359 t = realloc(r, n + 2);
de1c301e
LP
360 if (!t) {
361 free(r);
362 return -ENOMEM;
363 }
364
365 r = t;
366 r[n++] = c;
367 }
368
89ffcd2a
LP
369 if (!r) {
370 r = strdup("");
371 if (!r)
372 return -ENOMEM;
373 } else
374 r[n] = 0;
375
376 if (*a == ',')
377 a++;
378
de1c301e 379 *p = a;
2fd9ae2e
LP
380
381 free(*value);
de1c301e 382 *value = r;
2fd9ae2e 383
de1c301e
LP
384 return 1;
385}
386
387static void skip_address_key(const char **p) {
388 assert(p);
389 assert(*p);
390
89ffcd2a
LP
391 *p += strcspn(*p, ",");
392
393 if (**p == ',')
394 (*p) ++;
de1c301e
LP
395}
396
2fd9ae2e
LP
397static int parse_unix_address(sd_bus *b, const char **p, char **guid) {
398 _cleanup_free_ char *path = NULL, *abstract = NULL;
399 size_t l;
de1c301e
LP
400 int r;
401
402 assert(b);
2fd9ae2e
LP
403 assert(p);
404 assert(*p);
405 assert(guid);
de1c301e 406
2fd9ae2e
LP
407 while (**p != 0 && **p != ';') {
408 r = parse_address_key(p, "guid", guid);
409 if (r < 0)
410 return r;
411 else if (r > 0)
412 continue;
de1c301e 413
2fd9ae2e
LP
414 r = parse_address_key(p, "path", &path);
415 if (r < 0)
416 return r;
417 else if (r > 0)
418 continue;
de1c301e 419
2fd9ae2e
LP
420 r = parse_address_key(p, "abstract", &abstract);
421 if (r < 0)
422 return r;
423 else if (r > 0)
424 continue;
de1c301e 425
2fd9ae2e
LP
426 skip_address_key(p);
427 }
de1c301e 428
2fd9ae2e
LP
429 if (!path && !abstract)
430 return -EINVAL;
de1c301e 431
2fd9ae2e
LP
432 if (path && abstract)
433 return -EINVAL;
434
435 if (path) {
436 l = strlen(path);
437 if (l > sizeof(b->sockaddr.un.sun_path))
438 return -E2BIG;
de1c301e 439
2fd9ae2e
LP
440 b->sockaddr.un.sun_family = AF_UNIX;
441 strncpy(b->sockaddr.un.sun_path, path, sizeof(b->sockaddr.un.sun_path));
442 b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + l;
443 } else if (abstract) {
444 l = strlen(abstract);
445 if (l > sizeof(b->sockaddr.un.sun_path) - 1)
446 return -E2BIG;
447
448 b->sockaddr.un.sun_family = AF_UNIX;
449 b->sockaddr.un.sun_path[0] = 0;
450 strncpy(b->sockaddr.un.sun_path+1, abstract, sizeof(b->sockaddr.un.sun_path)-1);
451 b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + 1 + l;
452 }
453
454 return 0;
455}
456
457static int parse_tcp_address(sd_bus *b, const char **p, char **guid) {
458 _cleanup_free_ char *host = NULL, *port = NULL, *family = NULL;
2fd9ae2e 459 int r;
b92bea5d
ZJS
460 struct addrinfo *result, hints = {
461 .ai_socktype = SOCK_STREAM,
462 .ai_flags = AI_ADDRCONFIG,
463 };
2fd9ae2e
LP
464
465 assert(b);
466 assert(p);
467 assert(*p);
468 assert(guid);
469
470 while (**p != 0 && **p != ';') {
471 r = parse_address_key(p, "guid", guid);
472 if (r < 0)
473 return r;
474 else if (r > 0)
475 continue;
476
477 r = parse_address_key(p, "host", &host);
478 if (r < 0)
479 return r;
480 else if (r > 0)
481 continue;
482
483 r = parse_address_key(p, "port", &port);
484 if (r < 0)
485 return r;
486 else if (r > 0)
487 continue;
488
489 r = parse_address_key(p, "family", &family);
490 if (r < 0)
491 return r;
492 else if (r > 0)
493 continue;
494
495 skip_address_key(p);
496 }
497
498 if (!host || !port)
499 return -EINVAL;
500
2fd9ae2e
LP
501 if (family) {
502 if (streq(family, "ipv4"))
503 hints.ai_family = AF_INET;
504 else if (streq(family, "ipv6"))
505 hints.ai_family = AF_INET6;
506 else
507 return -EINVAL;
508 }
509
510 r = getaddrinfo(host, port, &hints, &result);
511 if (r == EAI_SYSTEM)
512 return -errno;
513 else if (r != 0)
514 return -EADDRNOTAVAIL;
515
516 memcpy(&b->sockaddr, result->ai_addr, result->ai_addrlen);
517 b->sockaddr_size = result->ai_addrlen;
518
519 freeaddrinfo(result);
520
521 return 0;
522}
523
524static int parse_exec_address(sd_bus *b, const char **p, char **guid) {
525 char *path = NULL;
526 unsigned n_argv = 0, j;
527 char **argv = NULL;
528 int r;
529
530 assert(b);
531 assert(p);
532 assert(*p);
533 assert(guid);
534
535 while (**p != 0 && **p != ';') {
536 r = parse_address_key(p, "guid", guid);
537 if (r < 0)
538 goto fail;
539 else if (r > 0)
540 continue;
541
542 r = parse_address_key(p, "path", &path);
543 if (r < 0)
544 goto fail;
545 else if (r > 0)
546 continue;
547
548 if (startswith(*p, "argv")) {
549 unsigned ul;
550
551 errno = 0;
552 ul = strtoul(*p + 4, (char**) p, 10);
8333c77e 553 if (errno > 0 || **p != '=' || ul > 256) {
2fd9ae2e
LP
554 r = -EINVAL;
555 goto fail;
556 }
557
558 (*p) ++;
559
560 if (ul >= n_argv) {
561 char **x;
562
563 x = realloc(argv, sizeof(char*) * (ul + 2));
564 if (!x) {
565 r = -ENOMEM;
566 goto fail;
567 }
568
569 memset(x + n_argv, 0, sizeof(char*) * (ul - n_argv + 2));
570
571 argv = x;
572 n_argv = ul + 1;
573 }
574
575 r = parse_address_key(p, NULL, argv + ul);
de1c301e 576 if (r < 0)
2fd9ae2e 577 goto fail;
de1c301e 578
2fd9ae2e 579 continue;
de1c301e
LP
580 }
581
2fd9ae2e
LP
582 skip_address_key(p);
583 }
de1c301e 584
5a0f6033
LP
585 if (!path) {
586 r = -EINVAL;
2fd9ae2e 587 goto fail;
5a0f6033 588 }
de1c301e 589
2fd9ae2e
LP
590 /* Make sure there are no holes in the array, with the
591 * exception of argv[0] */
592 for (j = 1; j < n_argv; j++)
593 if (!argv[j]) {
594 r = -EINVAL;
595 goto fail;
596 }
597
598 if (argv && argv[0] == NULL) {
599 argv[0] = strdup(path);
600 if (!argv[0]) {
601 r = -ENOMEM;
602 goto fail;
603 }
604 }
de1c301e 605
2fd9ae2e
LP
606 b->exec_path = path;
607 b->exec_argv = argv;
608 return 0;
de1c301e 609
2fd9ae2e
LP
610fail:
611 for (j = 0; j < n_argv; j++)
612 free(argv[j]);
613
614 free(argv);
615 free(path);
616 return r;
617}
618
6629161f
LP
619static int parse_kernel_address(sd_bus *b, const char **p, char **guid) {
620 _cleanup_free_ char *path = NULL;
621 int r;
622
623 assert(b);
624 assert(p);
625 assert(*p);
626 assert(guid);
627
628 while (**p != 0 && **p != ';') {
629 r = parse_address_key(p, "guid", guid);
630 if (r < 0)
631 return r;
632 else if (r > 0)
633 continue;
634
635 r = parse_address_key(p, "path", &path);
636 if (r < 0)
637 return r;
638 else if (r > 0)
639 continue;
640
641 skip_address_key(p);
642 }
643
644 if (!path)
645 return -EINVAL;
646
647 free(b->kernel);
648 b->kernel = path;
649 path = NULL;
650
651 return 0;
652}
653
2fd9ae2e
LP
654static void bus_reset_parsed_address(sd_bus *b) {
655 assert(b);
656
657 zero(b->sockaddr);
658 b->sockaddr_size = 0;
659 strv_free(b->exec_argv);
660 free(b->exec_path);
661 b->exec_path = NULL;
662 b->exec_argv = NULL;
98178d39 663 b->server_id = SD_ID128_NULL;
6629161f
LP
664 free(b->kernel);
665 b->kernel = NULL;
2fd9ae2e
LP
666}
667
668static int bus_parse_next_address(sd_bus *b) {
669 _cleanup_free_ char *guid = NULL;
670 const char *a;
671 int r;
672
673 assert(b);
674
675 if (!b->address)
676 return 0;
677 if (b->address[b->address_index] == 0)
678 return 0;
679
680 bus_reset_parsed_address(b);
681
682 a = b->address + b->address_index;
de1c301e 683
2fd9ae2e 684 while (*a != 0) {
de1c301e 685
2fd9ae2e
LP
686 if (*a == ';') {
687 a++;
688 continue;
de1c301e
LP
689 }
690
2fd9ae2e
LP
691 if (startswith(a, "unix:")) {
692 a += 5;
de1c301e 693
2fd9ae2e 694 r = parse_unix_address(b, &a, &guid);
de1c301e
LP
695 if (r < 0)
696 return r;
2fd9ae2e 697 break;
de1c301e 698
2fd9ae2e 699 } else if (startswith(a, "tcp:")) {
de1c301e 700
2fd9ae2e
LP
701 a += 4;
702 r = parse_tcp_address(b, &a, &guid);
de1c301e
LP
703 if (r < 0)
704 return r;
de1c301e 705
2fd9ae2e
LP
706 break;
707
708 } else if (startswith(a, "unixexec:")) {
709
710 a += 9;
711 r = parse_exec_address(b, &a, &guid);
de1c301e
LP
712 if (r < 0)
713 return r;
de1c301e 714
2fd9ae2e 715 break;
de1c301e 716
6629161f
LP
717 } else if (startswith(a, "kernel:")) {
718
719 a += 7;
720 r = parse_kernel_address(b, &a, &guid);
721 if (r < 0)
722 return r;
723
724 break;
de1c301e
LP
725 }
726
2fd9ae2e
LP
727 a = strchr(a, ';');
728 if (!a)
729 return 0;
de1c301e
LP
730 }
731
732 if (guid) {
98178d39 733 r = sd_id128_from_string(guid, &b->server_id);
de1c301e
LP
734 if (r < 0)
735 return r;
736 }
737
2fd9ae2e 738 b->address_index = a - b->address;
de1c301e
LP
739 return 1;
740}
741
a7e3212d 742static int bus_start_address(sd_bus *b) {
2fd9ae2e
LP
743 int r;
744
745 assert(b);
746
747 for (;;) {
e82c9509 748 sd_bus_close(b);
2fd9ae2e
LP
749
750 if (b->sockaddr.sa.sa_family != AF_UNSPEC) {
a7e3212d
LP
751
752 r = bus_socket_connect(b);
2fd9ae2e
LP
753 if (r >= 0)
754 return r;
755
756 b->last_connect_error = -r;
757
758 } else if (b->exec_path) {
759
a7e3212d 760 r = bus_socket_exec(b);
2fd9ae2e
LP
761 if (r >= 0)
762 return r;
763
6629161f
LP
764 b->last_connect_error = -r;
765 } else if (b->kernel) {
766
767 r = bus_kernel_connect(b);
768 if (r >= 0)
769 return r;
770
2fd9ae2e
LP
771 b->last_connect_error = -r;
772 }
773
774 r = bus_parse_next_address(b);
775 if (r < 0)
776 return r;
777 if (r == 0)
778 return b->last_connect_error ? -b->last_connect_error : -ECONNREFUSED;
de1c301e
LP
779 }
780}
781
a7e3212d
LP
782int bus_next_address(sd_bus *b) {
783 assert(b);
784
785 bus_reset_parsed_address(b);
786 return bus_start_address(b);
787}
788
021a1e78 789static int bus_start_fd(sd_bus *b) {
6629161f 790 struct stat st;
021a1e78
LP
791 int r;
792
793 assert(b);
e82c9509
LP
794 assert(b->input_fd >= 0);
795 assert(b->output_fd >= 0);
021a1e78 796
e82c9509 797 r = fd_nonblock(b->input_fd, true);
021a1e78
LP
798 if (r < 0)
799 return r;
800
e82c9509 801 r = fd_cloexec(b->input_fd, true);
021a1e78
LP
802 if (r < 0)
803 return r;
804
e82c9509
LP
805 if (b->input_fd != b->output_fd) {
806 r = fd_nonblock(b->output_fd, true);
807 if (r < 0)
808 return r;
809
810 r = fd_cloexec(b->output_fd, true);
811 if (r < 0)
812 return r;
813 }
814
6629161f
LP
815 if (fstat(b->input_fd, &st) < 0)
816 return -errno;
817
818 if (S_ISCHR(b->input_fd))
819 return bus_kernel_take_fd(b);
820 else
821 return bus_socket_take_fd(b);
021a1e78
LP
822}
823
824int sd_bus_start(sd_bus *bus) {
825 int r;
826
827 if (!bus)
828 return -EINVAL;
829 if (bus->state != BUS_UNSET)
830 return -EPERM;
831
832 bus->state = BUS_OPENING;
833
2181a7f5
LP
834 if (bus->is_server && bus->bus_client)
835 return -EINVAL;
836
e82c9509 837 if (bus->input_fd >= 0)
021a1e78 838 r = bus_start_fd(bus);
6629161f 839 else if (bus->address || bus->sockaddr.sa.sa_family != AF_UNSPEC || bus->exec_path || bus->kernel)
a7e3212d 840 r = bus_start_address(bus);
021a1e78
LP
841 else
842 return -EINVAL;
843
844 if (r < 0)
845 return r;
846
847 return bus_send_hello(bus);
848}
849
de1c301e
LP
850int sd_bus_open_system(sd_bus **ret) {
851 const char *e;
852 sd_bus *b;
853 int r;
854
855 if (!ret)
856 return -EINVAL;
857
021a1e78
LP
858 r = sd_bus_new(&b);
859 if (r < 0)
860 return r;
861
6c03089c 862 e = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
de1c301e 863 if (e) {
021a1e78 864 r = sd_bus_set_address(b, e);
de1c301e 865 if (r < 0)
021a1e78 866 goto fail;
89ffcd2a 867 } else {
89ffcd2a
LP
868 b->sockaddr.un.sun_family = AF_UNIX;
869 strncpy(b->sockaddr.un.sun_path, "/run/dbus/system_bus_socket", sizeof(b->sockaddr.un.sun_path));
870 b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/dbus/system_bus_socket") - 1;
89ffcd2a 871 }
de1c301e 872
94bbf1ba 873 b->bus_client = true;
021a1e78
LP
874
875 r = sd_bus_start(b);
876 if (r < 0)
877 goto fail;
de1c301e
LP
878
879 *ret = b;
880 return 0;
021a1e78
LP
881
882fail:
883 bus_free(b);
884 return r;
de1c301e
LP
885}
886
887int sd_bus_open_user(sd_bus **ret) {
888 const char *e;
889 sd_bus *b;
890 size_t l;
891 int r;
892
893 if (!ret)
894 return -EINVAL;
895
021a1e78
LP
896 r = sd_bus_new(&b);
897 if (r < 0)
898 return r;
899
6c03089c 900 e = secure_getenv("DBUS_SESSION_BUS_ADDRESS");
de1c301e 901 if (e) {
021a1e78 902 r = sd_bus_set_address(b, e);
de1c301e 903 if (r < 0)
021a1e78 904 goto fail;
89ffcd2a 905 } else {
6c03089c 906 e = secure_getenv("XDG_RUNTIME_DIR");
021a1e78
LP
907 if (!e) {
908 r = -ENOENT;
909 goto fail;
910 }
de1c301e 911
89ffcd2a 912 l = strlen(e);
021a1e78
LP
913 if (l + 4 > sizeof(b->sockaddr.un.sun_path)) {
914 r = -E2BIG;
915 goto fail;
916 }
de1c301e 917
89ffcd2a
LP
918 b->sockaddr.un.sun_family = AF_UNIX;
919 memcpy(mempcpy(b->sockaddr.un.sun_path, e, l), "/bus", 4);
920 b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + l + 4;
de1c301e
LP
921 }
922
94bbf1ba 923 b->bus_client = true;
de1c301e 924
021a1e78 925 r = sd_bus_start(b);
2571ead1
LP
926 if (r < 0)
927 goto fail;
de1c301e
LP
928
929 *ret = b;
930 return 0;
2571ead1
LP
931
932fail:
021a1e78 933 bus_free(b);
2571ead1 934 return r;
de1c301e
LP
935}
936
937void sd_bus_close(sd_bus *bus) {
938 if (!bus)
939 return;
de1c301e 940
f54514f3
LP
941 if (bus->state != BUS_CLOSED)
942 return;
943
944 bus->state = BUS_CLOSED;
e82c9509 945
f54514f3
LP
946 if (!bus->is_kernel)
947 bus_close_fds(bus);
948
949 /* We'll leave the fd open in case this is a kernel bus, since
950 * there might still be memblocks around that reference this
951 * bus, and they might need to invoke the
952 * KDBUS_CMD_MSG_RELEASE ioctl on the fd when they are
953 * freed. */
de1c301e
LP
954}
955
956sd_bus *sd_bus_ref(sd_bus *bus) {
957 if (!bus)
958 return NULL;
959
e4ee6e5c 960 assert_se(REFCNT_INC(bus->n_ref) >= 2);
de1c301e 961
de1c301e
LP
962 return bus;
963}
964
965sd_bus *sd_bus_unref(sd_bus *bus) {
966 if (!bus)
967 return NULL;
968
e4ee6e5c 969 if (REFCNT_DEC(bus->n_ref) <= 0)
de1c301e
LP
970 bus_free(bus);
971
972 return NULL;
973}
974
e3017af9
LP
975int sd_bus_is_open(sd_bus *bus) {
976 if (!bus)
977 return -EINVAL;
978
f54514f3 979 return BUS_IS_OPEN(bus->state);
e3017af9
LP
980}
981
d728d708
LP
982int sd_bus_can_send(sd_bus *bus, char type) {
983 int r;
984
de1c301e
LP
985 if (!bus)
986 return -EINVAL;
f54514f3 987 if (bus->state == BUS_UNSET)
021a1e78 988 return -ENOTCONN;
de1c301e 989
d728d708 990 if (type == SD_BUS_TYPE_UNIX_FD) {
021a1e78
LP
991 if (!bus->negotiate_fds)
992 return 0;
993
20902f3e 994 r = bus_ensure_running(bus);
d728d708
LP
995 if (r < 0)
996 return r;
de1c301e 997
d728d708
LP
998 return bus->can_fds;
999 }
1000
1001 return bus_type_is_valid(type);
de1c301e
LP
1002}
1003
98178d39 1004int sd_bus_get_server_id(sd_bus *bus, sd_id128_t *server_id) {
d728d708 1005 int r;
de1c301e
LP
1006
1007 if (!bus)
1008 return -EINVAL;
98178d39 1009 if (!server_id)
d728d708 1010 return -EINVAL;
de1c301e 1011
20902f3e 1012 r = bus_ensure_running(bus);
d728d708
LP
1013 if (r < 0)
1014 return r;
de1c301e 1015
98178d39 1016 *server_id = bus->server_id;
d728d708 1017 return 0;
de1c301e
LP
1018}
1019
1020static int bus_seal_message(sd_bus *b, sd_bus_message *m) {
1021 assert(m);
1022
89ffcd2a
LP
1023 if (m->header->version > b->message_version)
1024 return -EPERM;
1025
de1c301e
LP
1026 if (m->sealed)
1027 return 0;
1028
9a17484d 1029 return bus_message_seal(m, ++b->serial);
de1c301e
LP
1030}
1031
de1c301e 1032static int dispatch_wqueue(sd_bus *bus) {
e3017af9 1033 int r, ret = 0;
de1c301e
LP
1034
1035 assert(bus);
89ffcd2a 1036 assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
de1c301e 1037
de1c301e
LP
1038 while (bus->wqueue_size > 0) {
1039
6629161f
LP
1040 if (bus->is_kernel)
1041 r = bus_kernel_write_message(bus, bus->wqueue[0]);
1042 else
1043 r = bus_socket_write_message(bus, bus->wqueue[0], &bus->windex);
1044
de1c301e
LP
1045 if (r < 0) {
1046 sd_bus_close(bus);
1047 return r;
1048 } else if (r == 0)
e3017af9
LP
1049 /* Didn't do anything this time */
1050 return ret;
6629161f 1051 else if (bus->is_kernel || bus->windex >= BUS_MESSAGE_SIZE(bus->wqueue[0])) {
de1c301e
LP
1052 /* Fully written. Let's drop the entry from
1053 * the queue.
1054 *
1055 * This isn't particularly optimized, but
1056 * well, this is supposed to be our worst-case
1057 * buffer only, and the socket buffer is
1058 * supposed to be our primary buffer, and if
1059 * it got full, then all bets are off
1060 * anyway. */
1061
1062 sd_bus_message_unref(bus->wqueue[0]);
1063 bus->wqueue_size --;
1064 memmove(bus->wqueue, bus->wqueue + 1, sizeof(sd_bus_message*) * bus->wqueue_size);
1065 bus->windex = 0;
1066
e3017af9 1067 ret = 1;
de1c301e
LP
1068 }
1069 }
1070
e3017af9 1071 return ret;
de1c301e
LP
1072}
1073
1074static int dispatch_rqueue(sd_bus *bus, sd_bus_message **m) {
2bf938c1 1075 sd_bus_message *z = NULL;
e3017af9 1076 int r, ret = 0;
de1c301e
LP
1077
1078 assert(bus);
1079 assert(m);
89ffcd2a 1080 assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
de1c301e 1081
de1c301e
LP
1082 if (bus->rqueue_size > 0) {
1083 /* Dispatch a queued message */
1084
1085 *m = bus->rqueue[0];
1086 bus->rqueue_size --;
1087 memmove(bus->rqueue, bus->rqueue + 1, sizeof(sd_bus_message*) * bus->rqueue_size);
1088 return 1;
1089 }
1090
1091 /* Try to read a new message */
e3017af9 1092 do {
6629161f
LP
1093 if (bus->is_kernel)
1094 r = bus_kernel_read_message(bus, &z);
1095 else
1096 r = bus_socket_read_message(bus, &z);
1097
e3017af9
LP
1098 if (r < 0) {
1099 sd_bus_close(bus);
1100 return r;
1101 }
1102 if (r == 0)
1103 return ret;
de1c301e 1104
e3017af9
LP
1105 r = 1;
1106 } while (!z);
1107
1108 *m = z;
1109 return 1;
de1c301e
LP
1110}
1111
1112int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *serial) {
1113 int r;
1114
1115 if (!bus)
1116 return -EINVAL;
f54514f3 1117 if (!BUS_IS_OPEN(bus->state))
de1c301e
LP
1118 return -ENOTCONN;
1119 if (!m)
1120 return -EINVAL;
021a1e78
LP
1121
1122 if (m->n_fds > 0) {
1123 r = sd_bus_can_send(bus, SD_BUS_TYPE_UNIX_FD);
1124 if (r < 0)
1125 return r;
1126 if (r == 0)
1127 return -ENOTSUP;
1128 }
de1c301e 1129
29f6aadd
LP
1130 /* If the serial number isn't kept, then we know that no reply
1131 * is expected */
1132 if (!serial && !m->sealed)
1133 m->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
1134
de1c301e
LP
1135 r = bus_seal_message(bus, m);
1136 if (r < 0)
1137 return r;
1138
5407f2de
LP
1139 /* If this is a reply and no reply was requested, then let's
1140 * suppress this, if we can */
1141 if (m->dont_send && !serial)
1142 return 0;
1143
89ffcd2a 1144 if ((bus->state == BUS_RUNNING || bus->state == BUS_HELLO) && bus->wqueue_size <= 0) {
de1c301e
LP
1145 size_t idx = 0;
1146
6629161f
LP
1147 if (bus->is_kernel)
1148 r = bus_kernel_write_message(bus, m);
1149 else
1150 r = bus_socket_write_message(bus, m, &idx);
1151
de1c301e
LP
1152 if (r < 0) {
1153 sd_bus_close(bus);
1154 return r;
6629161f 1155 } else if (!bus->is_kernel && idx < BUS_MESSAGE_SIZE(m)) {
de1c301e
LP
1156 /* Wasn't fully written. So let's remember how
1157 * much was written. Note that the first entry
1158 * of the wqueue array is always allocated so
1159 * that we always can remember how much was
1160 * written. */
1161 bus->wqueue[0] = sd_bus_message_ref(m);
1162 bus->wqueue_size = 1;
1163 bus->windex = idx;
1164 }
1165 } else {
1166 sd_bus_message **q;
1167
1168 /* Just append it to the queue. */
1169
25220239 1170 if (bus->wqueue_size >= BUS_WQUEUE_MAX)
de1c301e
LP
1171 return -ENOBUFS;
1172
1173 q = realloc(bus->wqueue, sizeof(sd_bus_message*) * (bus->wqueue_size + 1));
1174 if (!q)
1175 return -ENOMEM;
1176
1177 bus->wqueue = q;
1178 q[bus->wqueue_size ++] = sd_bus_message_ref(m);
1179 }
1180
1181 if (serial)
1182 *serial = BUS_MESSAGE_SERIAL(m);
1183
1184 return 0;
1185}
1186
1187static usec_t calc_elapse(uint64_t usec) {
1188 if (usec == (uint64_t) -1)
1189 return 0;
1190
1191 if (usec == 0)
e3017af9 1192 usec = BUS_DEFAULT_TIMEOUT;
de1c301e
LP
1193
1194 return now(CLOCK_MONOTONIC) + usec;
1195}
1196
e3017af9
LP
1197static int timeout_compare(const void *a, const void *b) {
1198 const struct reply_callback *x = a, *y = b;
1199
1200 if (x->timeout != 0 && y->timeout == 0)
1201 return -1;
1202
1203 if (x->timeout == 0 && y->timeout != 0)
1204 return 1;
1205
1206 if (x->timeout < y->timeout)
1207 return -1;
1208
1209 if (x->timeout > y->timeout)
1210 return 1;
1211
1212 return 0;
1213}
1214
de1c301e
LP
1215int sd_bus_send_with_reply(
1216 sd_bus *bus,
1217 sd_bus_message *m,
52f3ba91 1218 sd_bus_message_handler_t callback,
de1c301e
LP
1219 void *userdata,
1220 uint64_t usec,
1221 uint64_t *serial) {
1222
1223 struct reply_callback *c;
1224 int r;
1225
1226 if (!bus)
1227 return -EINVAL;
f54514f3 1228 if (!BUS_IS_OPEN(bus->state))
de1c301e
LP
1229 return -ENOTCONN;
1230 if (!m)
1231 return -EINVAL;
1232 if (!callback)
1233 return -EINVAL;
89ffcd2a 1234 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
de1c301e 1235 return -EINVAL;
89ffcd2a
LP
1236 if (m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
1237 return -EINVAL;
1238
1239 r = hashmap_ensure_allocated(&bus->reply_callbacks, uint64_hash_func, uint64_compare_func);
1240 if (r < 0)
1241 return r;
de1c301e 1242
e3017af9
LP
1243 if (usec != (uint64_t) -1) {
1244 r = prioq_ensure_allocated(&bus->reply_callbacks_prioq, timeout_compare);
1245 if (r < 0)
1246 return r;
1247 }
1248
de1c301e
LP
1249 r = bus_seal_message(bus, m);
1250 if (r < 0)
1251 return r;
1252
eba8617e 1253 c = new0(struct reply_callback, 1);
de1c301e
LP
1254 if (!c)
1255 return -ENOMEM;
1256
1257 c->callback = callback;
1258 c->userdata = userdata;
1259 c->serial = BUS_MESSAGE_SERIAL(m);
1260 c->timeout = calc_elapse(usec);
1261
1262 r = hashmap_put(bus->reply_callbacks, &c->serial, c);
1263 if (r < 0) {
1264 free(c);
1265 return r;
1266 }
1267
e3017af9
LP
1268 if (c->timeout != 0) {
1269 r = prioq_put(bus->reply_callbacks_prioq, c, &c->prioq_idx);
1270 if (r < 0) {
1271 c->timeout = 0;
1272 sd_bus_send_with_reply_cancel(bus, c->serial);
1273 return r;
1274 }
1275 }
1276
de1c301e
LP
1277 r = sd_bus_send(bus, m, serial);
1278 if (r < 0) {
e3017af9 1279 sd_bus_send_with_reply_cancel(bus, c->serial);
de1c301e
LP
1280 return r;
1281 }
1282
1283 return r;
1284}
1285
1286int sd_bus_send_with_reply_cancel(sd_bus *bus, uint64_t serial) {
e3017af9 1287 struct reply_callback *c;
de1c301e
LP
1288
1289 if (!bus)
1290 return -EINVAL;
1291 if (serial == 0)
1292 return -EINVAL;
1293
1294 c = hashmap_remove(bus->reply_callbacks, &serial);
1295 if (!c)
1296 return 0;
1297
e3017af9
LP
1298 if (c->timeout != 0)
1299 prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
1300
de1c301e
LP
1301 free(c);
1302 return 1;
1303}
1304
20902f3e 1305int bus_ensure_running(sd_bus *bus) {
89ffcd2a
LP
1306 int r;
1307
1308 assert(bus);
1309
f54514f3 1310 if (bus->state == BUS_UNSET || bus->state == BUS_CLOSED)
021a1e78 1311 return -ENOTCONN;
d728d708
LP
1312 if (bus->state == BUS_RUNNING)
1313 return 1;
89ffcd2a
LP
1314
1315 for (;;) {
1316 r = sd_bus_process(bus, NULL);
1317 if (r < 0)
1318 return r;
d728d708
LP
1319 if (bus->state == BUS_RUNNING)
1320 return 1;
e3017af9
LP
1321 if (r > 0)
1322 continue;
89ffcd2a
LP
1323
1324 r = sd_bus_wait(bus, (uint64_t) -1);
1325 if (r < 0)
1326 return r;
1327 }
1328}
1329
de1c301e
LP
1330int sd_bus_send_with_reply_and_block(
1331 sd_bus *bus,
1332 sd_bus_message *m,
1333 uint64_t usec,
1334 sd_bus_error *error,
1335 sd_bus_message **reply) {
1336
1337 int r;
1338 usec_t timeout;
1339 uint64_t serial;
1340 bool room = false;
1341
1342 if (!bus)
1343 return -EINVAL;
f54514f3 1344 if (!BUS_IS_OPEN(bus->state))
021a1e78 1345 return -ENOTCONN;
de1c301e
LP
1346 if (!m)
1347 return -EINVAL;
89ffcd2a 1348 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
de1c301e 1349 return -EINVAL;
89ffcd2a 1350 if (m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
de1c301e 1351 return -EINVAL;
89ffcd2a
LP
1352 if (bus_error_is_dirty(error))
1353 return -EINVAL;
1354
20902f3e 1355 r = bus_ensure_running(bus);
89ffcd2a
LP
1356 if (r < 0)
1357 return r;
de1c301e
LP
1358
1359 r = sd_bus_send(bus, m, &serial);
1360 if (r < 0)
1361 return r;
1362
1363 timeout = calc_elapse(usec);
1364
1365 for (;;) {
1366 usec_t left;
e3017af9 1367 sd_bus_message *incoming = NULL;
de1c301e
LP
1368
1369 if (!room) {
1370 sd_bus_message **q;
1371
25220239
LP
1372 if (bus->rqueue_size >= BUS_RQUEUE_MAX)
1373 return -ENOBUFS;
1374
de1c301e
LP
1375 /* Make sure there's room for queuing this
1376 * locally, before we read the message */
1377
1378 q = realloc(bus->rqueue, (bus->rqueue_size + 1) * sizeof(sd_bus_message*));
1379 if (!q)
1380 return -ENOMEM;
1381
1382 bus->rqueue = q;
1383 room = true;
1384 }
1385
6629161f
LP
1386 if (bus->is_kernel)
1387 r = bus_kernel_read_message(bus, &incoming);
1388 else
1389 r = bus_socket_read_message(bus, &incoming);
de1c301e
LP
1390 if (r < 0)
1391 return r;
e3017af9 1392 if (incoming) {
89ffcd2a 1393
de1c301e
LP
1394 if (incoming->reply_serial == serial) {
1395 /* Found a match! */
1396
1397 if (incoming->header->type == SD_BUS_MESSAGE_TYPE_METHOD_RETURN) {
b7f247e0
LP
1398
1399 if (reply)
1400 *reply = incoming;
1401 else
1402 sd_bus_message_unref(incoming);
1403
de1c301e
LP
1404 return 0;
1405 }
1406
1407 if (incoming->header->type == SD_BUS_MESSAGE_TYPE_METHOD_ERROR) {
1408 int k;
1409
1410 r = sd_bus_error_copy(error, &incoming->error);
1411 if (r < 0) {
1412 sd_bus_message_unref(incoming);
1413 return r;
1414 }
1415
1416 k = bus_error_to_errno(&incoming->error);
1417 sd_bus_message_unref(incoming);
1418 return k;
1419 }
1420
1421 sd_bus_message_unref(incoming);
1422 return -EIO;
1423 }
1424
1425 /* There's already guaranteed to be room for
1426 * this, so need to resize things here */
1427 bus->rqueue[bus->rqueue_size ++] = incoming;
1428 room = false;
1429
1430 /* Try to read more, right-away */
1431 continue;
1432 }
e3017af9
LP
1433 if (r != 0)
1434 continue;
de1c301e
LP
1435
1436 if (timeout > 0) {
1437 usec_t n;
1438
1439 n = now(CLOCK_MONOTONIC);
1440 if (n >= timeout)
1441 return -ETIMEDOUT;
1442
1443 left = timeout - n;
1444 } else
1445 left = (uint64_t) -1;
1446
e3017af9 1447 r = bus_poll(bus, true, left);
de1c301e
LP
1448 if (r < 0)
1449 return r;
1450
1451 r = dispatch_wqueue(bus);
1452 if (r < 0)
1453 return r;
1454 }
1455}
1456
1457int sd_bus_get_fd(sd_bus *bus) {
1458 if (!bus)
1459 return -EINVAL;
f54514f3 1460 if (!BUS_IS_OPEN(bus->state))
89ffcd2a 1461 return -ENOTCONN;
e82c9509
LP
1462 if (bus->input_fd != bus->output_fd)
1463 return -EPERM;
de1c301e 1464
e82c9509 1465 return bus->input_fd;
de1c301e
LP
1466}
1467
1468int sd_bus_get_events(sd_bus *bus) {
1469 int flags = 0;
1470
1471 if (!bus)
1472 return -EINVAL;
f54514f3 1473 if (!BUS_IS_OPEN(bus->state))
89ffcd2a 1474 return -ENOTCONN;
de1c301e
LP
1475
1476 if (bus->state == BUS_OPENING)
1477 flags |= POLLOUT;
89ffcd2a
LP
1478 else if (bus->state == BUS_AUTHENTICATING) {
1479
2181a7f5 1480 if (bus_socket_auth_needs_write(bus))
89ffcd2a
LP
1481 flags |= POLLOUT;
1482
1483 flags |= POLLIN;
1484
1485 } else if (bus->state == BUS_RUNNING || bus->state == BUS_HELLO) {
de1c301e
LP
1486 if (bus->rqueue_size <= 0)
1487 flags |= POLLIN;
1488 if (bus->wqueue_size > 0)
1489 flags |= POLLOUT;
1490 }
1491
1492 return flags;
1493}
1494
e3017af9
LP
1495int sd_bus_get_timeout(sd_bus *bus, uint64_t *timeout_usec) {
1496 struct reply_callback *c;
1497
1498 if (!bus)
1499 return -EINVAL;
1500 if (!timeout_usec)
1501 return -EINVAL;
f54514f3 1502 if (!BUS_IS_OPEN(bus->state))
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;
de1c301e 1999
6807947e
LP
2000 /* We don't allow recursively invoking sd_bus_process(). */
2001 if (bus->processing)
2002 return -EBUSY;
2003
a7e3212d 2004 switch (bus->state) {
de1c301e 2005
a7e3212d 2006 case BUS_UNSET:
f54514f3 2007 case BUS_CLOSED:
a7e3212d 2008 return -ENOTCONN;
de1c301e 2009
a7e3212d
LP
2010 case BUS_OPENING:
2011 r = bus_socket_process_opening(bus);
2012 if (r < 0)
2013 return r;
2014 if (ret)
2015 *ret = NULL;
2016 return r;
b9bf7e2b 2017
a7e3212d 2018 case BUS_AUTHENTICATING:
89ffcd2a 2019
a7e3212d
LP
2020 r = bus_socket_process_authenticating(bus);
2021 if (r < 0)
2022 return r;
2023 if (ret)
2024 *ret = NULL;
2025 return r;
89ffcd2a 2026
a7e3212d
LP
2027 case BUS_RUNNING:
2028 case BUS_HELLO:
89ffcd2a 2029
6807947e
LP
2030 bus->processing = true;
2031 r = process_running(bus, ret);
2032 bus->processing = false;
2033
2034 return r;
de1c301e
LP
2035 }
2036
89ffcd2a 2037 assert_not_reached("Unknown state");
de1c301e
LP
2038}
2039
e3017af9 2040static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec) {
b92bea5d 2041 struct pollfd p[2] = {};
e82c9509 2042 int r, e, n;
de1c301e 2043 struct timespec ts;
e3017af9
LP
2044 usec_t until, m;
2045
2046 assert(bus);
de1c301e 2047
f54514f3 2048 if (!BUS_IS_OPEN(bus->state))
89ffcd2a
LP
2049 return -ENOTCONN;
2050
de1c301e
LP
2051 e = sd_bus_get_events(bus);
2052 if (e < 0)
2053 return e;
2054
e3017af9
LP
2055 if (need_more)
2056 e |= POLLIN;
2057
2058 r = sd_bus_get_timeout(bus, &until);
2059 if (r < 0)
2060 return r;
2061 if (r == 0)
2062 m = (uint64_t) -1;
2063 else {
e82c9509
LP
2064 usec_t nw;
2065 nw = now(CLOCK_MONOTONIC);
2066 m = until > nw ? until - nw : 0;
e3017af9
LP
2067 }
2068
2069 if (timeout_usec != (uint64_t) -1 && (m == (uint64_t) -1 || timeout_usec < m))
2070 m = timeout_usec;
2071
e82c9509 2072 p[0].fd = bus->input_fd;
e82c9509
LP
2073 if (bus->output_fd == bus->input_fd) {
2074 p[0].events = e;
2075 n = 1;
2076 } else {
2077 p[0].events = e & POLLIN;
2078 p[1].fd = bus->output_fd;
2079 p[1].events = e & POLLOUT;
2080 n = 2;
2081 }
de1c301e 2082
e82c9509 2083 r = ppoll(p, n, m == (uint64_t) -1 ? NULL : timespec_store(&ts, m), NULL);
de1c301e 2084 if (r < 0)
89ffcd2a 2085 return -errno;
de1c301e 2086
e3017af9
LP
2087 return r > 0 ? 1 : 0;
2088}
2089
2090int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec) {
2091
2092 if (!bus)
2093 return -EINVAL;
f54514f3 2094 if (!BUS_IS_OPEN(bus->state))
e3017af9
LP
2095 return -ENOTCONN;
2096 if (bus->rqueue_size > 0)
2097 return 0;
2098
2099 return bus_poll(bus, false, timeout_usec);
de1c301e
LP
2100}
2101
2102int sd_bus_flush(sd_bus *bus) {
2103 int r;
2104
2105 if (!bus)
2106 return -EINVAL;
f54514f3 2107 if (!BUS_IS_OPEN(bus->state))
de1c301e
LP
2108 return -ENOTCONN;
2109
20902f3e 2110 r = bus_ensure_running(bus);
89ffcd2a
LP
2111 if (r < 0)
2112 return r;
2113
2114 if (bus->wqueue_size <= 0)
de1c301e
LP
2115 return 0;
2116
2117 for (;;) {
2118 r = dispatch_wqueue(bus);
2119 if (r < 0)
2120 return r;
2121
89ffcd2a 2122 if (bus->wqueue_size <= 0)
de1c301e
LP
2123 return 0;
2124
e3017af9 2125 r = bus_poll(bus, false, (uint64_t) -1);
de1c301e
LP
2126 if (r < 0)
2127 return r;
2128 }
2129}
2130
52f3ba91 2131int sd_bus_add_filter(sd_bus *bus, sd_bus_message_handler_t callback, void *userdata) {
de1c301e
LP
2132 struct filter_callback *f;
2133
2134 if (!bus)
2135 return -EINVAL;
2136 if (!callback)
2137 return -EINVAL;
2138
eba8617e 2139 f = new0(struct filter_callback, 1);
de1c301e
LP
2140 if (!f)
2141 return -ENOMEM;
2142 f->callback = callback;
2143 f->userdata = userdata;
2144
7286037f 2145 bus->filter_callbacks_modified = true;
de1c301e
LP
2146 LIST_PREPEND(struct filter_callback, callbacks, bus->filter_callbacks, f);
2147 return 0;
2148}
2149
52f3ba91 2150int sd_bus_remove_filter(sd_bus *bus, sd_bus_message_handler_t callback, void *userdata) {
de1c301e
LP
2151 struct filter_callback *f;
2152
2153 if (!bus)
2154 return -EINVAL;
2155 if (!callback)
2156 return -EINVAL;
2157
2158 LIST_FOREACH(callbacks, f, bus->filter_callbacks) {
2159 if (f->callback == callback && f->userdata == userdata) {
7286037f 2160 bus->filter_callbacks_modified = true;
de1c301e
LP
2161 LIST_REMOVE(struct filter_callback, callbacks, bus->filter_callbacks, f);
2162 free(f);
2163 return 1;
2164 }
2165 }
2166
2167 return 0;
2168}
a652755d
LP
2169
2170static int bus_add_object(
2171 sd_bus *bus,
2172 bool fallback,
2173 const char *path,
52f3ba91 2174 sd_bus_message_handler_t callback,
a652755d
LP
2175 void *userdata) {
2176
2177 struct object_callback *c;
2178 int r;
2179
2180 if (!bus)
2181 return -EINVAL;
2182 if (!path)
2183 return -EINVAL;
2184 if (!callback)
2185 return -EINVAL;
2186
2187 r = hashmap_ensure_allocated(&bus->object_callbacks, string_hash_func, string_compare_func);
2188 if (r < 0)
2189 return r;
2190
eba8617e 2191 c = new0(struct object_callback, 1);
a652755d
LP
2192 if (!c)
2193 return -ENOMEM;
2194
2195 c->path = strdup(path);
531991b6 2196 if (!c->path) {
a652755d
LP
2197 free(c);
2198 return -ENOMEM;
2199 }
2200
2201 c->callback = callback;
2202 c->userdata = userdata;
2203 c->is_fallback = fallback;
2204
7286037f 2205 bus->object_callbacks_modified = true;
a652755d
LP
2206 r = hashmap_put(bus->object_callbacks, c->path, c);
2207 if (r < 0) {
2208 free(c->path);
2209 free(c);
2210 return r;
2211 }
2212
2213 return 0;
2214}
2215
2216static int bus_remove_object(
2217 sd_bus *bus,
2218 bool fallback,
2219 const char *path,
52f3ba91 2220 sd_bus_message_handler_t callback,
a652755d
LP
2221 void *userdata) {
2222
2223 struct object_callback *c;
2224
2225 if (!bus)
2226 return -EINVAL;
2227 if (!path)
2228 return -EINVAL;
2229 if (!callback)
2230 return -EINVAL;
2231
2232 c = hashmap_get(bus->object_callbacks, path);
2233 if (!c)
2234 return 0;
2235
2236 if (c->callback != callback || c->userdata != userdata || c->is_fallback != fallback)
2237 return 0;
2238
7286037f 2239 bus->object_callbacks_modified = true;
a652755d
LP
2240 assert_se(c == hashmap_remove(bus->object_callbacks, c->path));
2241
2242 free(c->path);
2243 free(c);
2244
2245 return 1;
2246}
2247
52f3ba91 2248int sd_bus_add_object(sd_bus *bus, const char *path, sd_bus_message_handler_t callback, void *userdata) {
a652755d
LP
2249 return bus_add_object(bus, false, path, callback, userdata);
2250}
2251
52f3ba91 2252int sd_bus_remove_object(sd_bus *bus, const char *path, sd_bus_message_handler_t callback, void *userdata) {
a652755d
LP
2253 return bus_remove_object(bus, false, path, callback, userdata);
2254}
2255
52f3ba91 2256int sd_bus_add_fallback(sd_bus *bus, const char *prefix, sd_bus_message_handler_t callback, void *userdata) {
a652755d
LP
2257 return bus_add_object(bus, true, prefix, callback, userdata);
2258}
2259
52f3ba91 2260int sd_bus_remove_fallback(sd_bus *bus, const char *prefix, sd_bus_message_handler_t callback, void *userdata) {
a652755d
LP
2261 return bus_remove_object(bus, true, prefix, callback, userdata);
2262}
392d5b37 2263
52f3ba91 2264int sd_bus_add_match(sd_bus *bus, const char *match, sd_bus_message_handler_t callback, void *userdata) {
392d5b37
LP
2265 int r = 0;
2266
2267 if (!bus)
2268 return -EINVAL;
2269 if (!match)
2270 return -EINVAL;
2271
2272 if (bus->bus_client) {
2273 r = bus_add_match_internal(bus, match);
2274 if (r < 0)
2275 return r;
2276 }
2277
2278 if (callback) {
7286037f 2279 bus->match_callbacks_modified = true;
392d5b37
LP
2280 r = bus_match_add(&bus->match_callbacks, match, callback, userdata, NULL);
2281 if (r < 0) {
2282
2283 if (bus->bus_client)
2284 bus_remove_match_internal(bus, match);
2285 }
2286 }
2287
2288 return r;
2289}
2290
52f3ba91 2291int sd_bus_remove_match(sd_bus *bus, const char *match, sd_bus_message_handler_t callback, void *userdata) {
392d5b37
LP
2292 int r = 0, q = 0;
2293
2294 if (!bus)
2295 return -EINVAL;
2296 if (!match)
2297 return -EINVAL;
2298
2299 if (bus->bus_client)
2300 r = bus_remove_match_internal(bus, match);
2301
7286037f
LP
2302 if (callback) {
2303 bus->match_callbacks_modified = true;
392d5b37 2304 q = bus_match_remove(&bus->match_callbacks, match, callback, userdata);
7286037f 2305 }
392d5b37
LP
2306
2307 if (r < 0)
2308 return r;
2309 return q;
2310}
917b5dc7
LP
2311
2312int sd_bus_emit_signal(
2313 sd_bus *bus,
2314 const char *path,
2315 const char *interface,
2316 const char *member,
2317 const char *types, ...) {
2318
2319 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2320 va_list ap;
2321 int r;
2322
2323 if (!bus)
2324 return -EINVAL;
2325
2326 r = sd_bus_message_new_signal(bus, path, interface, member, &m);
2327 if (r < 0)
2328 return r;
2329
2330 va_start(ap, types);
2331 r = bus_message_append_ap(m, types, ap);
2332 va_end(ap);
2333 if (r < 0)
2334 return r;
2335
2336 return sd_bus_send(bus, m, NULL);
2337}
2338
2339int sd_bus_call_method(
2340 sd_bus *bus,
2341 const char *destination,
2342 const char *path,
2343 const char *interface,
2344 const char *member,
2345 sd_bus_error *error,
2346 sd_bus_message **reply,
2347 const char *types, ...) {
2348
2349 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2350 va_list ap;
2351 int r;
2352
2353 if (!bus)
2354 return -EINVAL;
2355
2356 r = sd_bus_message_new_method_call(bus, destination, path, interface, member, &m);
2357 if (r < 0)
2358 return r;
2359
2360 va_start(ap, types);
2361 r = bus_message_append_ap(m, types, ap);
2362 va_end(ap);
2363 if (r < 0)
2364 return r;
2365
2366 return sd_bus_send_with_reply_and_block(bus, m, 0, error, reply);
2367}
f10dda3b
LP
2368
2369int sd_bus_reply_method_return(
2370 sd_bus *bus,
2371 sd_bus_message *call,
2372 const char *types, ...) {
2373
2374 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2375 va_list ap;
2376 int r;
2377
2378 if (!bus)
2379 return -EINVAL;
2380 if (!call)
2381 return -EINVAL;
2382 if (!call->sealed)
2383 return -EPERM;
2384 if (call->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
2385 return -EINVAL;
2386
2387 if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
2388 return 0;
2389
2390 r = sd_bus_message_new_method_return(bus, call, &m);
2391 if (r < 0)
2392 return r;
2393
2394 va_start(ap, types);
2395 r = bus_message_append_ap(m, types, ap);
2396 va_end(ap);
2397 if (r < 0)
2398 return r;
2399
2400 return sd_bus_send(bus, m, NULL);
2401}
2402
2403int sd_bus_reply_method_error(
2404 sd_bus *bus,
2405 sd_bus_message *call,
2406 const sd_bus_error *e) {
2407
2408 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2409 int r;
2410
2411 if (!bus)
2412 return -EINVAL;
2413 if (!call)
2414 return -EINVAL;
2415 if (!call->sealed)
2416 return -EPERM;
2417 if (call->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
2418 return -EINVAL;
2419 if (!sd_bus_error_is_set(e))
2420 return -EINVAL;
2421
2422 if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
2423 return 0;
2424
2425 r = sd_bus_message_new_method_error(bus, call, e, &m);
2426 if (r < 0)
2427 return r;
2428
2429 return sd_bus_send(bus, m, NULL);
2430}