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