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"
36 static int object_callback(sd_bus *bus, int error, sd_bus_message *m, void *userdata) {
44 if (sd_bus_message_is_method_call(m, "org.object.test", "Foobar")) {
45 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
47 log_info("Invoked Foobar() on %s", sd_bus_message_get_path(m));
49 r = sd_bus_message_new_method_return(bus, m, &reply);
51 log_error("Failed to allocate return: %s", strerror(-r));
55 r = sd_bus_send(bus, reply, NULL);
57 log_error("Failed to send reply: %s", strerror(-r));
67 static int server_init(sd_bus **_bus) {
75 r = sd_bus_open_user(&bus);
77 log_error("Failed to connect to user bus: %s", strerror(-r));
81 r = sd_bus_get_peer(bus, &id);
83 log_error("Failed to get peer ID: %s", strerror(-r));
87 r = sd_bus_get_unique_name(bus, &unique);
89 log_error("Failed to get unique name: %s", strerror(-r));
93 log_info("Peer ID is " SD_ID128_FORMAT_STR ".", SD_ID128_FORMAT_VAL(id));
94 log_info("Unique ID: %s", unique);
95 log_info("Can send file handles: %i", sd_bus_can_send(bus, 'h'));
97 r = sd_bus_request_name(bus, "org.freedesktop.systemd.test", 0);
99 log_error("Failed to acquire name: %s", strerror(-r));
103 r = sd_bus_add_fallback(bus, "/foo/bar", object_callback, NULL);
105 log_error("Failed to add object: %s", strerror(-r));
119 static int server(sd_bus *bus) {
121 bool client1_gone = false, client2_gone = false;
123 while (!client1_gone || !client2_gone) {
124 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
127 r = sd_bus_process(bus, &m);
129 log_error("Failed to process requests: %s", strerror(-r));
134 r = sd_bus_wait(bus, (uint64_t) -1);
136 log_error("Failed to wait: %s", strerror(-r));
146 sd_bus_message_get_pid(m, &pid);
147 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)));
148 /* bus_message_dump(m); */
149 /* sd_bus_message_rewind(m, true); */
151 if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "LowerCase")) {
153 _cleanup_free_ char *lowercase = NULL;
155 r = sd_bus_message_read(m, "s", &hello);
157 log_error("Failed to get parameter: %s", strerror(-r));
161 r = sd_bus_message_new_method_return(bus, m, &reply);
163 log_error("Failed to allocate return: %s", strerror(-r));
167 lowercase = strdup(hello);
173 ascii_strlower(lowercase);
175 r = sd_bus_message_append(reply, "s", lowercase);
177 log_error("Failed to append message: %s", strerror(-r));
180 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient1")) {
182 r = sd_bus_message_new_method_return(bus, m, &reply);
184 log_error("Failed to allocate return: %s", strerror(-r));
189 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient2")) {
191 r = sd_bus_message_new_method_return(bus, m, &reply);
193 log_error("Failed to allocate return: %s", strerror(-r));
198 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Slow")) {
200 r = sd_bus_message_new_method_return(bus, m, &reply);
202 log_error("Failed to allocate return: %s", strerror(-r));
208 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "FileDescriptor")) {
210 static const char x = 'X';
212 r = sd_bus_message_read(m, "h", &fd);
214 log_error("Failed to get parameter: %s", strerror(-r));
218 if (write(fd, &x, 1) < 0) {
219 log_error("Failed to write to fd: %m");
220 close_nointr_nofail(fd);
224 close_nointr_nofail(fd);
226 r = sd_bus_message_new_method_return(bus, m, &reply);
228 log_error("Failed to allocate return: %s", strerror(-r));
232 } else if (sd_bus_message_is_method_call(m, NULL, NULL)) {
233 const sd_bus_error e = SD_BUS_ERROR_INIT_CONST("org.freedesktop.DBus.Error.UnknownMethod", "Unknown method.");
235 r = sd_bus_message_new_method_error(bus, m, &e, &reply);
237 log_error("Failed to allocate return: %s", strerror(-r));
243 r = sd_bus_send(bus, reply, NULL);
245 log_error("Failed to send reply: %s", strerror(-r));
249 /* log_info("Sent"); */
250 /* bus_message_dump(reply); */
251 /* sd_bus_message_rewind(reply, true); */
266 static void* client1(void*p) {
267 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
269 sd_bus_error error = SD_BUS_ERROR_INIT;
272 int pp[2] = { -1, -1 };
275 r = sd_bus_open_user(&bus);
277 log_error("Failed to connect to user bus: %s", strerror(-r));
281 r = sd_bus_message_new_method_call(
283 "org.freedesktop.systemd.test",
285 "org.freedesktop.systemd.test",
289 log_error("Failed to allocate method call: %s", strerror(-r));
293 r = sd_bus_message_append(m, "s", "HELLO");
295 log_error("Failed to append string: %s", strerror(-r));
299 r = sd_bus_send_with_reply_and_block(bus, m, 0, &error, &reply);
301 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
305 r = sd_bus_message_read(reply, "s", &hello);
307 log_error("Failed to get string: %s", strerror(-r));
311 assert(streq(hello, "hello"));
313 if (pipe2(pp, O_CLOEXEC|O_NONBLOCK) < 0) {
314 log_error("Failed to allocate pipe: %m");
319 sd_bus_message_unref(m);
321 r = sd_bus_message_new_method_call(
323 "org.freedesktop.systemd.test",
325 "org.freedesktop.systemd.test",
329 log_error("Failed to allocate method call: %s", strerror(-r));
333 r = sd_bus_message_append(m, "h", pp[1]);
335 log_error("Failed to append string: %s", strerror(-r));
339 sd_bus_message_unref(reply);
341 r = sd_bus_send_with_reply_and_block(bus, m, 0, &error, &reply);
343 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
348 if (read(pp[0], &x, 1) <= 0) {
349 log_error("Failed to read from pipe: %s", errno ? strerror(errno) : "early read");
357 _cleanup_bus_message_unref_ sd_bus_message *q;
359 r = sd_bus_message_new_method_call(
361 "org.freedesktop.systemd.test",
363 "org.freedesktop.systemd.test",
367 log_error("Failed to allocate method call: %s", strerror(-r));
371 sd_bus_send(bus, q, NULL);
376 sd_bus_error_free(&error);
380 return INT_TO_PTR(r);
383 static int quit_callback(sd_bus *b, int ret, sd_bus_message *m, void *userdata) {
386 log_error("Quit callback: %s", strerror(ret));
392 static void* client2(void*p) {
393 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
395 sd_bus_error error = SD_BUS_ERROR_INIT;
400 r = sd_bus_open_user(&bus);
402 log_error("Failed to connect to user bus: %s", strerror(-r));
406 r = sd_bus_message_new_method_call(
408 "org.freedesktop.systemd.test",
409 "/foo/bar/waldo/piep",
414 log_error("Failed to allocate method call: %s", strerror(-r));
418 r = sd_bus_send(bus, m, NULL);
420 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
424 sd_bus_message_unref(m);
427 r = sd_bus_message_new_method_call(
429 "org.freedesktop.systemd.test",
431 "org.freedesktop.DBus.Peer",
435 log_error("Failed to allocate method call: %s", strerror(-r));
439 r = sd_bus_send_with_reply_and_block(bus, m, 0, &error, &reply);
441 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
445 r = sd_bus_message_read(reply, "s", &mid);
447 log_error("Failed to parse machine ID: %s", strerror(-r));
451 log_info("Machine ID is %s.", mid);
453 sd_bus_message_unref(m);
456 r = sd_bus_message_new_method_call(
458 "org.freedesktop.systemd.test",
460 "org.freedesktop.systemd.test",
464 log_error("Failed to allocate method call: %s", strerror(-r));
468 sd_bus_message_unref(reply);
471 r = sd_bus_send_with_reply_and_block(bus, m, 200 * USEC_PER_MSEC, &error, &reply);
473 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
475 log_info("Slow call succeed.");
477 sd_bus_message_unref(m);
480 r = sd_bus_message_new_method_call(
482 "org.freedesktop.systemd.test",
484 "org.freedesktop.systemd.test",
488 log_error("Failed to allocate method call: %s", strerror(-r));
492 r = sd_bus_send_with_reply(bus, m, quit_callback, &quit, 200 * USEC_PER_MSEC, NULL);
494 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
499 r = sd_bus_process(bus, NULL);
501 log_error("Failed to process requests: %s", strerror(-r));
505 r = sd_bus_wait(bus, (uint64_t) -1);
507 log_error("Failed to wait: %s", strerror(-r));
517 _cleanup_bus_message_unref_ sd_bus_message *q;
519 r = sd_bus_message_new_method_call(
521 "org.freedesktop.systemd.test",
523 "org.freedesktop.systemd.test",
527 log_error("Failed to allocate method call: %s", strerror(-r));
531 sd_bus_send(bus, q, NULL);
536 sd_bus_error_free(&error);
537 return INT_TO_PTR(r);
540 int main(int argc, char *argv[]) {
546 r = server_init(&bus);
548 log_info("Failed to connect to bus, skipping tests.");
549 return EXIT_TEST_SKIP;
552 log_info("Initialized...");
554 r = pthread_create(&c1, NULL, client1, bus);
558 r = pthread_create(&c2, NULL, client2, bus);
564 q = pthread_join(c1, &p);
567 q = pthread_join(c2, &p);