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 r = sd_bus_reply_method_return(bus, m, NULL);
235 log_error("Failed to send reply: %s", strerror(-r));
239 } else if (sd_bus_message_is_method_call(m, NULL, NULL)) {
241 r = sd_bus_reply_method_error(
243 &SD_BUS_ERROR_MAKE("org.freedesktop.DBus.Error.UnknownMethod", "Unknown method."));
245 log_error("Failed to send reply: %s", strerror(-r));
262 static void* client1(void*p) {
263 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
265 sd_bus_error error = SD_BUS_ERROR_NULL;
268 int pp[2] = { -1, -1 };
271 r = sd_bus_open_user(&bus);
273 log_error("Failed to connect to user bus: %s", strerror(-r));
277 r = sd_bus_call_method(
279 "org.freedesktop.systemd.test",
281 "org.freedesktop.systemd.test",
288 log_error("Failed to issue method call: %s", strerror(-r));
292 r = sd_bus_message_read(reply, "s", &hello);
294 log_error("Failed to get string: %s", strerror(-r));
298 assert(streq(hello, "hello"));
300 if (pipe2(pp, O_CLOEXEC|O_NONBLOCK) < 0) {
301 log_error("Failed to allocate pipe: %m");
306 r = sd_bus_call_method(
308 "org.freedesktop.systemd.test",
310 "org.freedesktop.systemd.test",
317 log_error("Failed to issue method call: %s", strerror(-r));
322 if (read(pp[0], &x, 1) <= 0) {
323 log_error("Failed to read from pipe: %s", errno ? strerror(errno) : "early read");
331 _cleanup_bus_message_unref_ sd_bus_message *q;
333 r = sd_bus_message_new_method_call(
335 "org.freedesktop.systemd.test",
337 "org.freedesktop.systemd.test",
341 log_error("Failed to allocate method call: %s", strerror(-r));
343 sd_bus_send(bus, q, NULL);
349 sd_bus_error_free(&error);
353 return INT_TO_PTR(r);
356 static int quit_callback(sd_bus *b, int ret, sd_bus_message *m, void *userdata) {
359 log_error("Quit callback: %s", strerror(ret));
365 static void* client2(void*p) {
366 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
368 sd_bus_error error = SD_BUS_ERROR_NULL;
373 r = sd_bus_open_user(&bus);
375 log_error("Failed to connect to user bus: %s", strerror(-r));
379 r = sd_bus_message_new_method_call(
381 "org.freedesktop.systemd.test",
382 "/foo/bar/waldo/piep",
387 log_error("Failed to allocate method call: %s", strerror(-r));
391 r = sd_bus_send(bus, m, NULL);
393 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
397 sd_bus_message_unref(m);
400 r = sd_bus_message_new_signal(
407 log_error("Failed to allocate signal: %s", strerror(-r));
411 r = sd_bus_send(bus, m, NULL);
413 log_error("Failed to issue signal: %s", bus_error_message(&error, -r));
417 sd_bus_message_unref(m);
420 r = sd_bus_message_new_method_call(
422 "org.freedesktop.systemd.test",
424 "org.freedesktop.DBus.Peer",
428 log_error("Failed to allocate method call: %s", strerror(-r));
432 r = sd_bus_send_with_reply_and_block(bus, m, 0, &error, &reply);
434 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
438 r = sd_bus_message_read(reply, "s", &mid);
440 log_error("Failed to parse machine ID: %s", strerror(-r));
444 log_info("Machine ID is %s.", mid);
446 sd_bus_message_unref(m);
449 r = sd_bus_message_new_method_call(
451 "org.freedesktop.systemd.test",
453 "org.freedesktop.systemd.test",
457 log_error("Failed to allocate method call: %s", strerror(-r));
461 sd_bus_message_unref(reply);
464 r = sd_bus_send_with_reply_and_block(bus, m, 200 * USEC_PER_MSEC, &error, &reply);
466 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
468 log_info("Slow call succeed.");
470 sd_bus_message_unref(m);
473 r = sd_bus_message_new_method_call(
475 "org.freedesktop.systemd.test",
477 "org.freedesktop.systemd.test",
481 log_error("Failed to allocate method call: %s", strerror(-r));
485 r = sd_bus_send_with_reply(bus, m, quit_callback, &quit, 200 * USEC_PER_MSEC, NULL);
487 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
492 r = sd_bus_process(bus, NULL);
494 log_error("Failed to process requests: %s", strerror(-r));
498 r = sd_bus_wait(bus, (uint64_t) -1);
500 log_error("Failed to wait: %s", strerror(-r));
510 _cleanup_bus_message_unref_ sd_bus_message *q;
512 r = sd_bus_message_new_method_call(
514 "org.freedesktop.systemd.test",
516 "org.freedesktop.systemd.test",
520 log_error("Failed to allocate method call: %s", strerror(-r));
524 sd_bus_send(bus, q, NULL);
529 sd_bus_error_free(&error);
530 return INT_TO_PTR(r);
533 int main(int argc, char *argv[]) {
539 r = server_init(&bus);
541 log_info("Failed to connect to bus, skipping tests.");
542 return EXIT_TEST_SKIP;
545 log_info("Initialized...");
547 r = pthread_create(&c1, NULL, client1, bus);
551 r = pthread_create(&c2, NULL, client2, bus);
557 q = pthread_join(c1, &p);
560 if (PTR_TO_INT(p) < 0)
563 q = pthread_join(c2, &p);
566 if (PTR_TO_INT(p) < 0)