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, int error, 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, int error, sd_bus_message *m, void *userdata) {
51 if (sd_bus_message_is_method_call(m, "org.object.test", "Foobar")) {
52 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
54 log_info("Invoked Foobar() on %s", sd_bus_message_get_path(m));
56 r = sd_bus_reply_method_return(bus, m, NULL);
58 log_error("Failed to send reply: %s", strerror(-r));
68 static int server_init(sd_bus **_bus) {
76 r = sd_bus_open_user(&bus);
78 log_error("Failed to connect to user bus: %s", strerror(-r));
82 r = sd_bus_get_server_id(bus, &id);
84 log_error("Failed to get server ID: %s", strerror(-r));
88 r = sd_bus_get_unique_name(bus, &unique);
90 log_error("Failed to get unique name: %s", strerror(-r));
94 log_info("Peer ID is " SD_ID128_FORMAT_STR ".", SD_ID128_FORMAT_VAL(id));
95 log_info("Unique ID: %s", unique);
96 log_info("Can send file handles: %i", sd_bus_can_send(bus, 'h'));
98 r = sd_bus_request_name(bus, "org.freedesktop.systemd.test", 0);
100 log_error("Failed to acquire name: %s", strerror(-r));
104 r = sd_bus_add_fallback(bus, "/foo/bar", object_callback, NULL);
106 log_error("Failed to add object: %s", strerror(-r));
110 r = sd_bus_add_match(bus, "type='signal',interface='foo.bar',member='Notify'", match_callback, NULL);
112 log_error("Failed to add match: %s", strerror(-r));
116 r = sd_bus_add_match(bus, "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged'", match_callback, NULL);
118 log_error("Failed to add match: %s", strerror(-r));
122 bus_match_dump(&bus->match_callbacks, 0);
134 static int server(sd_bus *bus) {
136 bool client1_gone = false, client2_gone = false;
138 while (!client1_gone || !client2_gone) {
139 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
142 r = sd_bus_process(bus, &m);
144 log_error("Failed to process requests: %s", strerror(-r));
149 r = sd_bus_wait(bus, (uint64_t) -1);
151 log_error("Failed to wait: %s", strerror(-r));
161 sd_bus_message_get_pid(m, &pid);
162 log_info("Got message! member=%s pid=%lu label=%s", strna(sd_bus_message_get_member(m)), (unsigned long) pid, strna(sd_bus_message_get_label(m)));
163 /* bus_message_dump(m); */
164 /* sd_bus_message_rewind(m, true); */
166 if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "LowerCase")) {
168 _cleanup_free_ char *lowercase = NULL;
170 r = sd_bus_message_read(m, "s", &hello);
172 log_error("Failed to get parameter: %s", strerror(-r));
176 lowercase = strdup(hello);
182 ascii_strlower(lowercase);
184 r = sd_bus_reply_method_return(bus, m, "s", lowercase);
186 log_error("Failed to send reply: %s", strerror(-r));
189 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient1")) {
191 r = sd_bus_reply_method_return(bus, m, NULL);
193 log_error("Failed to send reply: %s", strerror(-r));
198 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient2")) {
200 r = sd_bus_reply_method_return(bus, m, NULL);
202 log_error("Failed to send reply: %s", strerror(-r));
207 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Slow")) {
211 r = sd_bus_reply_method_return(bus, m, NULL);
213 log_error("Failed to send reply: %s", strerror(-r));
217 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "FileDescriptor")) {
219 static const char x = 'X';
221 r = sd_bus_message_read(m, "h", &fd);
223 log_error("Failed to get parameter: %s", strerror(-r));
227 if (write(fd, &x, 1) < 0) {
228 log_error("Failed to write to fd: %m");
229 close_nointr_nofail(fd);
233 close_nointr_nofail(fd);
235 r = sd_bus_reply_method_return(bus, m, NULL);
237 log_error("Failed to send reply: %s", strerror(-r));
241 } else if (sd_bus_message_is_method_call(m, NULL, NULL)) {
243 r = sd_bus_reply_method_error(
245 &SD_BUS_ERROR_MAKE("org.freedesktop.DBus.Error.UnknownMethod", "Unknown method."));
247 log_error("Failed to send reply: %s", strerror(-r));
264 static void* client1(void*p) {
265 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
267 sd_bus_error error = SD_BUS_ERROR_NULL;
270 int pp[2] = { -1, -1 };
273 r = sd_bus_open_user(&bus);
275 log_error("Failed to connect to user bus: %s", strerror(-r));
279 r = sd_bus_call_method(
281 "org.freedesktop.systemd.test",
283 "org.freedesktop.systemd.test",
290 log_error("Failed to issue method call: %s", strerror(-r));
294 r = sd_bus_message_read(reply, "s", &hello);
296 log_error("Failed to get string: %s", strerror(-r));
300 assert(streq(hello, "hello"));
302 if (pipe2(pp, O_CLOEXEC|O_NONBLOCK) < 0) {
303 log_error("Failed to allocate pipe: %m");
308 r = sd_bus_call_method(
310 "org.freedesktop.systemd.test",
312 "org.freedesktop.systemd.test",
319 log_error("Failed to issue method call: %s", strerror(-r));
324 if (read(pp[0], &x, 1) <= 0) {
325 log_error("Failed to read from pipe: %s", errno ? strerror(errno) : "early read");
333 _cleanup_bus_message_unref_ sd_bus_message *q;
335 r = sd_bus_message_new_method_call(
337 "org.freedesktop.systemd.test",
339 "org.freedesktop.systemd.test",
343 log_error("Failed to allocate method call: %s", strerror(-r));
345 sd_bus_send(bus, q, NULL);
351 sd_bus_error_free(&error);
355 return INT_TO_PTR(r);
358 static int quit_callback(sd_bus *b, int ret, sd_bus_message *m, void *userdata) {
361 log_error("Quit callback: %s", strerror(ret));
367 static void* client2(void*p) {
368 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
370 sd_bus_error error = SD_BUS_ERROR_NULL;
375 r = sd_bus_open_user(&bus);
377 log_error("Failed to connect to user bus: %s", strerror(-r));
381 r = sd_bus_message_new_method_call(
383 "org.freedesktop.systemd.test",
384 "/foo/bar/waldo/piep",
389 log_error("Failed to allocate method call: %s", strerror(-r));
393 r = sd_bus_send(bus, m, NULL);
395 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
399 sd_bus_message_unref(m);
402 r = sd_bus_message_new_signal(
409 log_error("Failed to allocate signal: %s", strerror(-r));
413 r = sd_bus_send(bus, m, NULL);
415 log_error("Failed to issue signal: %s", bus_error_message(&error, -r));
419 sd_bus_message_unref(m);
422 r = sd_bus_message_new_method_call(
424 "org.freedesktop.systemd.test",
426 "org.freedesktop.DBus.Peer",
430 log_error("Failed to allocate method call: %s", strerror(-r));
434 r = sd_bus_send_with_reply_and_block(bus, m, 0, &error, &reply);
436 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
440 r = sd_bus_message_read(reply, "s", &mid);
442 log_error("Failed to parse machine ID: %s", strerror(-r));
446 log_info("Machine ID is %s.", mid);
448 sd_bus_message_unref(m);
451 r = sd_bus_message_new_method_call(
453 "org.freedesktop.systemd.test",
455 "org.freedesktop.systemd.test",
459 log_error("Failed to allocate method call: %s", strerror(-r));
463 sd_bus_message_unref(reply);
466 r = sd_bus_send_with_reply_and_block(bus, m, 200 * USEC_PER_MSEC, &error, &reply);
468 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
470 log_info("Slow call succeed.");
472 sd_bus_message_unref(m);
475 r = sd_bus_message_new_method_call(
477 "org.freedesktop.systemd.test",
479 "org.freedesktop.systemd.test",
483 log_error("Failed to allocate method call: %s", strerror(-r));
487 r = sd_bus_send_with_reply(bus, m, quit_callback, &quit, 200 * USEC_PER_MSEC, NULL);
489 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
494 r = sd_bus_process(bus, NULL);
496 log_error("Failed to process requests: %s", strerror(-r));
500 r = sd_bus_wait(bus, (uint64_t) -1);
502 log_error("Failed to wait: %s", strerror(-r));
512 _cleanup_bus_message_unref_ sd_bus_message *q;
514 r = sd_bus_message_new_method_call(
516 "org.freedesktop.systemd.test",
518 "org.freedesktop.systemd.test",
522 log_error("Failed to allocate method call: %s", strerror(-r));
526 sd_bus_send(bus, q, NULL);
531 sd_bus_error_free(&error);
532 return INT_TO_PTR(r);
535 int main(int argc, char *argv[]) {
541 r = server_init(&bus);
543 log_info("Failed to connect to bus, skipping tests.");
544 return EXIT_TEST_SKIP;
547 log_info("Initialized...");
549 r = pthread_create(&c1, NULL, client1, bus);
553 r = pthread_create(&c2, NULL, client2, bus);
559 q = pthread_join(c1, &p);
562 if (PTR_TO_INT(p) < 0)
565 q = pthread_join(c2, &p);
568 if (PTR_TO_INT(p) < 0)