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/>.
33 #include "bus-message.h"
34 #include "bus-error.h"
35 #include "bus-match.h"
36 #include "bus-internal.h"
38 static int match_callback(sd_bus *bus, sd_bus_message *m, void *userdata) {
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) {
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(bus, m, NULL);
56 log_error("Failed to send reply: %s", strerror(-r));
66 static int server_init(sd_bus **_bus) {
74 r = sd_bus_open_user(&bus);
76 log_error("Failed to connect to user bus: %s", strerror(-r));
80 r = sd_bus_get_server_id(bus, &id);
82 log_error("Failed to get server ID: %s", strerror(-r));
86 r = sd_bus_get_unique_name(bus, &unique);
88 log_error("Failed to get unique name: %s", strerror(-r));
92 log_info("Peer ID is " SD_ID128_FORMAT_STR ".", SD_ID128_FORMAT_VAL(id));
93 log_info("Unique ID: %s", unique);
94 log_info("Can send file handles: %i", sd_bus_can_send(bus, 'h'));
96 r = sd_bus_request_name(bus, "org.freedesktop.systemd.test", 0);
98 log_error("Failed to acquire name: %s", strerror(-r));
102 r = sd_bus_add_fallback(bus, "/foo/bar", object_callback, NULL);
104 log_error("Failed to add object: %s", strerror(-r));
108 r = sd_bus_add_match(bus, "type='signal',interface='foo.bar',member='Notify'", match_callback, NULL);
110 log_error("Failed to add match: %s", strerror(-r));
114 r = sd_bus_add_match(bus, "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged'", match_callback, NULL);
116 log_error("Failed to add match: %s", strerror(-r));
120 bus_match_dump(&bus->match_callbacks, 0);
132 static int server(sd_bus *bus) {
134 bool client1_gone = false, client2_gone = false;
136 while (!client1_gone || !client2_gone) {
137 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
139 const char *label = NULL;
141 r = sd_bus_process(bus, &m);
143 log_error("Failed to process requests: %s", strerror(-r));
148 r = sd_bus_wait(bus, (uint64_t) -1);
150 log_error("Failed to wait: %s", strerror(-r));
160 sd_bus_message_get_pid(m, &pid);
161 sd_bus_message_get_selinux_context(m, &label);
162 log_info("Got message! member=%s pid=%lu label=%s",
163 strna(sd_bus_message_get_member(m)),
166 /* bus_message_dump(m); */
167 /* sd_bus_message_rewind(m, true); */
169 if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "LowerCase")) {
171 _cleanup_free_ char *lowercase = NULL;
173 r = sd_bus_message_read(m, "s", &hello);
175 log_error("Failed to get parameter: %s", strerror(-r));
179 lowercase = strdup(hello);
185 ascii_strlower(lowercase);
187 r = sd_bus_reply_method_return(bus, m, "s", lowercase);
189 log_error("Failed to send reply: %s", strerror(-r));
192 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient1")) {
194 r = sd_bus_reply_method_return(bus, m, NULL);
196 log_error("Failed to send reply: %s", strerror(-r));
201 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient2")) {
203 r = sd_bus_reply_method_return(bus, m, NULL);
205 log_error("Failed to send reply: %s", strerror(-r));
210 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Slow")) {
214 r = sd_bus_reply_method_return(bus, m, NULL);
216 log_error("Failed to send reply: %s", strerror(-r));
220 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "FileDescriptor")) {
222 static const char x = 'X';
224 r = sd_bus_message_read(m, "h", &fd);
226 log_error("Failed to get parameter: %s", strerror(-r));
230 if (write(fd, &x, 1) < 0) {
231 log_error("Failed to write to fd: %m");
232 close_nointr_nofail(fd);
236 r = sd_bus_reply_method_return(bus, m, NULL);
238 log_error("Failed to send reply: %s", strerror(-r));
242 } else if (sd_bus_message_is_method_call(m, NULL, NULL)) {
244 r = sd_bus_reply_method_error(
246 &SD_BUS_ERROR_MAKE("org.freedesktop.DBus.Error.UnknownMethod", "Unknown method."));
248 log_error("Failed to send reply: %s", strerror(-r));
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("Failed to connect to user bus: %s", strerror(-r));
280 r = sd_bus_call_method(
282 "org.freedesktop.systemd.test",
284 "org.freedesktop.systemd.test",
291 log_error("Failed to issue method call: %s", strerror(-r));
295 r = sd_bus_message_read(reply, "s", &hello);
297 log_error("Failed to get string: %s", strerror(-r));
301 assert(streq(hello, "hello"));
303 if (pipe2(pp, O_CLOEXEC|O_NONBLOCK) < 0) {
304 log_error("Failed to allocate pipe: %m");
309 r = sd_bus_call_method(
311 "org.freedesktop.systemd.test",
313 "org.freedesktop.systemd.test",
320 log_error("Failed to issue method call: %s", strerror(-r));
325 if (read(pp[0], &x, 1) <= 0) {
326 log_error("Failed to read from pipe: %s", errno ? strerror(errno) : "early read");
334 _cleanup_bus_message_unref_ sd_bus_message *q;
336 r = sd_bus_message_new_method_call(
338 "org.freedesktop.systemd.test",
340 "org.freedesktop.systemd.test",
344 log_error("Failed to allocate method call: %s", strerror(-r));
346 sd_bus_send(bus, q, NULL);
352 sd_bus_error_free(&error);
356 return INT_TO_PTR(r);
359 static int quit_callback(sd_bus *b, sd_bus_message *m, void *userdata) {
362 log_error("Quit callback: %s", strerror(bus_message_to_errno(m)));
368 static void* client2(void*p) {
369 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
371 sd_bus_error error = SD_BUS_ERROR_NULL;
376 r = sd_bus_open_user(&bus);
378 log_error("Failed to connect to user bus: %s", strerror(-r));
382 r = sd_bus_message_new_method_call(
384 "org.freedesktop.systemd.test",
385 "/foo/bar/waldo/piep",
390 log_error("Failed to allocate method call: %s", strerror(-r));
394 r = sd_bus_send(bus, m, NULL);
396 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
400 sd_bus_message_unref(m);
403 r = sd_bus_message_new_signal(
410 log_error("Failed to allocate signal: %s", strerror(-r));
414 r = sd_bus_send(bus, m, NULL);
416 log_error("Failed to issue signal: %s", bus_error_message(&error, -r));
420 sd_bus_message_unref(m);
423 r = sd_bus_message_new_method_call(
425 "org.freedesktop.systemd.test",
427 "org.freedesktop.DBus.Peer",
431 log_error("Failed to allocate method call: %s", strerror(-r));
435 r = sd_bus_send_with_reply_and_block(bus, m, 0, &error, &reply);
437 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
441 r = sd_bus_message_read(reply, "s", &mid);
443 log_error("Failed to parse machine ID: %s", strerror(-r));
447 log_info("Machine ID is %s.", mid);
449 sd_bus_message_unref(m);
452 r = sd_bus_message_new_method_call(
454 "org.freedesktop.systemd.test",
456 "org.freedesktop.systemd.test",
460 log_error("Failed to allocate method call: %s", strerror(-r));
464 sd_bus_message_unref(reply);
467 r = sd_bus_send_with_reply_and_block(bus, m, 200 * USEC_PER_MSEC, &error, &reply);
469 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
471 log_info("Slow call succeed.");
473 sd_bus_message_unref(m);
476 r = sd_bus_message_new_method_call(
478 "org.freedesktop.systemd.test",
480 "org.freedesktop.systemd.test",
484 log_error("Failed to allocate method call: %s", strerror(-r));
488 r = sd_bus_send_with_reply(bus, m, quit_callback, &quit, 200 * USEC_PER_MSEC, NULL);
490 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
495 r = sd_bus_process(bus, NULL);
497 log_error("Failed to process requests: %s", strerror(-r));
501 r = sd_bus_wait(bus, (uint64_t) -1);
503 log_error("Failed to wait: %s", strerror(-r));
513 _cleanup_bus_message_unref_ sd_bus_message *q;
515 r = sd_bus_message_new_method_call(
517 "org.freedesktop.systemd.test",
519 "org.freedesktop.systemd.test",
523 log_error("Failed to allocate method call: %s", strerror(-r));
527 sd_bus_send(bus, q, NULL);
532 sd_bus_error_free(&error);
533 return INT_TO_PTR(r);
536 int main(int argc, char *argv[]) {
542 r = server_init(&bus);
544 log_info("Failed to connect to bus, skipping tests.");
545 return EXIT_TEST_SKIP;
548 log_info("Initialized...");
550 r = pthread_create(&c1, NULL, client1, bus);
554 r = pthread_create(&c2, NULL, client2, bus);
560 q = pthread_join(c1, &p);
563 if (PTR_TO_INT(p) < 0)
566 q = pthread_join(c2, &p);
569 if (PTR_TO_INT(p) < 0)