1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
32 #include "bus-message.h"
33 #include "bus-error.h"
34 #include "bus-match.h"
35 #include "bus-internal.h"
38 static int match_callback(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
39 log_info("Match triggered! interface=%s member=%s", strna(sd_bus_message_get_interface(m)), strna(sd_bus_message_get_member(m)));
43 static int object_callback(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
48 if (sd_bus_message_is_method_error(m, NULL))
51 if (sd_bus_message_is_method_call(m, "org.object.test", "Foobar")) {
52 log_info("Invoked Foobar() on %s", sd_bus_message_get_path(m));
54 r = sd_bus_reply_method_return(m, NULL);
56 return log_error_errno(r, "Failed to send reply: %m");
64 static int server_init(sd_bus **_bus) {
72 r = sd_bus_open_user(&bus);
74 log_error_errno(r, "Failed to connect to user bus: %m");
78 r = sd_bus_get_bus_id(bus, &id);
80 log_error_errno(r, "Failed to get server ID: %m");
84 r = sd_bus_get_unique_name(bus, &unique);
86 log_error_errno(r, "Failed to get unique name: %m");
90 log_info("Peer ID is " SD_ID128_FORMAT_STR ".", SD_ID128_FORMAT_VAL(id));
91 log_info("Unique ID: %s", unique);
92 log_info("Can send file handles: %i", sd_bus_can_send(bus, 'h'));
94 r = sd_bus_request_name(bus, "org.freedesktop.systemd.test", 0);
96 log_error_errno(r, "Failed to acquire name: %m");
100 r = sd_bus_add_fallback(bus, NULL, "/foo/bar", object_callback, NULL);
102 log_error_errno(r, "Failed to add object: %m");
106 r = sd_bus_add_match(bus, NULL, "type='signal',interface='foo.bar',member='Notify'", match_callback, NULL);
108 log_error_errno(r, "Failed to add match: %m");
112 r = sd_bus_add_match(bus, NULL, "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged'", match_callback, NULL);
114 log_error_errno(r, "Failed to add match: %m");
118 bus_match_dump(&bus->match_callbacks, 0);
130 static int server(sd_bus *bus) {
132 bool client1_gone = false, client2_gone = false;
134 while (!client1_gone || !client2_gone) {
135 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
137 const char *label = NULL;
139 r = sd_bus_process(bus, &m);
141 log_error_errno(r, "Failed to process requests: %m");
146 r = sd_bus_wait(bus, (uint64_t) -1);
148 log_error_errno(r, "Failed to wait: %m");
158 sd_bus_creds_get_pid(sd_bus_message_get_creds(m), &pid);
159 sd_bus_creds_get_selinux_context(sd_bus_message_get_creds(m), &label);
160 log_info("Got message! member=%s pid="PID_FMT" label=%s",
161 strna(sd_bus_message_get_member(m)),
164 /* bus_message_dump(m); */
165 /* sd_bus_message_rewind(m, true); */
167 if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "LowerCase")) {
169 _cleanup_free_ char *lowercase = NULL;
171 r = sd_bus_message_read(m, "s", &hello);
173 log_error_errno(r, "Failed to get parameter: %m");
177 lowercase = strdup(hello);
183 ascii_strlower(lowercase);
185 r = sd_bus_reply_method_return(m, "s", lowercase);
187 log_error_errno(r, "Failed to send reply: %m");
190 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient1")) {
192 r = sd_bus_reply_method_return(m, NULL);
194 log_error_errno(r, "Failed to send reply: %m");
199 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient2")) {
201 r = sd_bus_reply_method_return(m, NULL);
203 log_error_errno(r, "Failed to send reply: %m");
208 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Slow")) {
212 r = sd_bus_reply_method_return(m, NULL);
214 log_error_errno(r, "Failed to send reply: %m");
218 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "FileDescriptor")) {
220 static const char x = 'X';
222 r = sd_bus_message_read(m, "h", &fd);
224 log_error_errno(r, "Failed to get parameter: %m");
228 log_info("Received fd=%d", fd);
230 if (write(fd, &x, 1) < 0) {
231 log_error_errno(errno, "Failed to write to fd: %m");
236 r = sd_bus_reply_method_return(m, NULL);
238 log_error_errno(r, "Failed to send reply: %m");
242 } else if (sd_bus_message_is_method_call(m, NULL, NULL)) {
244 r = sd_bus_reply_method_error(
246 &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method."));
248 log_error_errno(r, "Failed to send reply: %m");
265 static void* client1(void*p) {
266 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
268 sd_bus_error error = SD_BUS_ERROR_NULL;
271 int pp[2] = { -1, -1 };
274 r = sd_bus_open_user(&bus);
276 log_error_errno(r, "Failed to connect to user bus: %m");
280 r = sd_bus_call_method(
282 "org.freedesktop.systemd.test",
284 "org.freedesktop.systemd.test",
291 log_error_errno(r, "Failed to issue method call: %m");
295 r = sd_bus_message_read(reply, "s", &hello);
297 log_error_errno(r, "Failed to get string: %m");
301 assert_se(streq(hello, "hello"));
303 if (pipe2(pp, O_CLOEXEC|O_NONBLOCK) < 0) {
304 log_error_errno(errno, "Failed to allocate pipe: %m");
309 log_info("Sending fd=%d", pp[1]);
311 r = sd_bus_call_method(
313 "org.freedesktop.systemd.test",
315 "org.freedesktop.systemd.test",
322 log_error_errno(r, "Failed to issue method call: %m");
327 if (read(pp[0], &x, 1) <= 0) {
328 log_error("Failed to read from pipe: %s", errno ? strerror(errno) : "early read");
336 _cleanup_bus_message_unref_ sd_bus_message *q;
338 r = sd_bus_message_new_method_call(
341 "org.freedesktop.systemd.test",
343 "org.freedesktop.systemd.test",
346 log_error_errno(r, "Failed to allocate method call: %m");
348 sd_bus_send(bus, q, NULL);
354 sd_bus_error_free(&error);
358 return INT_TO_PTR(r);
361 static int quit_callback(sd_bus *b, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
364 log_error("Quit callback: %s", strerror(sd_bus_message_get_errno(m)));
370 static void* client2(void*p) {
371 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
373 sd_bus_error error = SD_BUS_ERROR_NULL;
378 r = sd_bus_open_user(&bus);
380 log_error_errno(r, "Failed to connect to user bus: %m");
384 r = sd_bus_message_new_method_call(
387 "org.freedesktop.systemd.test",
388 "/foo/bar/waldo/piep",
392 log_error_errno(r, "Failed to allocate method call: %m");
396 r = sd_bus_send(bus, m, NULL);
398 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
402 sd_bus_message_unref(m);
405 r = sd_bus_message_new_signal(
412 log_error_errno(r, "Failed to allocate signal: %m");
416 r = sd_bus_send(bus, m, NULL);
418 log_error("Failed to issue signal: %s", bus_error_message(&error, -r));
422 sd_bus_message_unref(m);
425 r = sd_bus_message_new_method_call(
428 "org.freedesktop.systemd.test",
430 "org.freedesktop.DBus.Peer",
433 log_error_errno(r, "Failed to allocate method call: %m");
437 r = sd_bus_call(bus, m, 0, &error, &reply);
439 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
443 r = sd_bus_message_read(reply, "s", &mid);
445 log_error_errno(r, "Failed to parse machine ID: %m");
449 log_info("Machine ID is %s.", mid);
451 sd_bus_message_unref(m);
454 r = sd_bus_message_new_method_call(
457 "org.freedesktop.systemd.test",
459 "org.freedesktop.systemd.test",
462 log_error_errno(r, "Failed to allocate method call: %m");
466 sd_bus_message_unref(reply);
469 r = sd_bus_call(bus, m, 200 * USEC_PER_MSEC, &error, &reply);
471 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
473 log_info("Slow call succeed.");
475 sd_bus_message_unref(m);
478 r = sd_bus_message_new_method_call(
481 "org.freedesktop.systemd.test",
483 "org.freedesktop.systemd.test",
486 log_error_errno(r, "Failed to allocate method call: %m");
490 r = sd_bus_call_async(bus, NULL, m, quit_callback, &quit, 200 * USEC_PER_MSEC);
492 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
497 r = sd_bus_process(bus, NULL);
499 log_error_errno(r, "Failed to process requests: %m");
503 r = sd_bus_wait(bus, (uint64_t) -1);
505 log_error_errno(r, "Failed to wait: %m");
515 _cleanup_bus_message_unref_ sd_bus_message *q;
517 r = sd_bus_message_new_method_call(
520 "org.freedesktop.systemd.test",
522 "org.freedesktop.systemd.test",
525 log_error_errno(r, "Failed to allocate method call: %m");
529 sd_bus_send(bus, q, NULL);
534 sd_bus_error_free(&error);
535 return INT_TO_PTR(r);
538 int main(int argc, char *argv[]) {
544 r = server_init(&bus);
546 log_info("Failed to connect to bus, skipping tests.");
547 return EXIT_TEST_SKIP;
550 log_info("Initialized...");
552 r = pthread_create(&c1, NULL, client1, bus);
556 r = pthread_create(&c2, NULL, client2, bus);
562 q = pthread_join(c1, &p);
565 if (PTR_TO_INT(p) < 0)
568 q = pthread_join(c2, &p);
571 if (PTR_TO_INT(p) < 0)