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"
39 static int match_callback(sd_bus *bus, sd_bus_message *m, void *userdata) {
40 log_info("Match triggered! interface=%s member=%s", strna(sd_bus_message_get_interface(m)), strna(sd_bus_message_get_member(m)));
44 static int object_callback(sd_bus *bus, sd_bus_message *m, void *userdata) {
49 if (sd_bus_message_is_method_error(m, NULL))
52 if (sd_bus_message_is_method_call(m, "org.object.test", "Foobar")) {
53 log_info("Invoked Foobar() on %s", sd_bus_message_get_path(m));
55 r = sd_bus_reply_method_return(bus, m, 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_server_id(bus, &id);
83 log_error("Failed to get server 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));
109 r = sd_bus_add_match(bus, "type='signal',interface='foo.bar',member='Notify'", match_callback, NULL);
111 log_error("Failed to add match: %s", strerror(-r));
115 r = sd_bus_add_match(bus, "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged'", match_callback, NULL);
117 log_error("Failed to add match: %s", strerror(-r));
121 bus_match_dump(&bus->match_callbacks, 0);
133 static int server(sd_bus *bus) {
135 bool client1_gone = false, client2_gone = false;
137 while (!client1_gone || !client2_gone) {
138 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
140 const char *label = 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 sd_bus_message_get_selinux_context(m, &label);
163 log_info("Got message! member=%s pid=%lu label=%s",
164 strna(sd_bus_message_get_member(m)),
167 /* bus_message_dump(m); */
168 /* sd_bus_message_rewind(m, true); */
170 if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "LowerCase")) {
172 _cleanup_free_ char *lowercase = NULL;
174 r = sd_bus_message_read(m, "s", &hello);
176 log_error("Failed to get parameter: %s", strerror(-r));
180 lowercase = strdup(hello);
186 ascii_strlower(lowercase);
188 r = sd_bus_reply_method_return(bus, m, "s", lowercase);
190 log_error("Failed to send reply: %s", strerror(-r));
193 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient1")) {
195 r = sd_bus_reply_method_return(bus, m, NULL);
197 log_error("Failed to send reply: %s", strerror(-r));
202 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient2")) {
204 r = sd_bus_reply_method_return(bus, m, NULL);
206 log_error("Failed to send reply: %s", strerror(-r));
211 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Slow")) {
215 r = sd_bus_reply_method_return(bus, m, NULL);
217 log_error("Failed to send reply: %s", strerror(-r));
221 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "FileDescriptor")) {
223 static const char x = 'X';
225 r = sd_bus_message_read(m, "h", &fd);
227 log_error("Failed to get parameter: %s", strerror(-r));
231 if (write(fd, &x, 1) < 0) {
232 log_error("Failed to write to fd: %m");
233 close_nointr_nofail(fd);
237 r = sd_bus_reply_method_return(bus, m, NULL);
239 log_error("Failed to send reply: %s", strerror(-r));
243 } else if (sd_bus_message_is_method_call(m, NULL, NULL)) {
245 r = sd_bus_reply_method_error(
247 &SD_BUS_ERROR_MAKE(SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method."));
249 log_error("Failed to send reply: %s", strerror(-r));
266 static void* client1(void*p) {
267 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
269 sd_bus_error error = SD_BUS_ERROR_NULL;
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_call_method(
283 "org.freedesktop.systemd.test",
285 "org.freedesktop.systemd.test",
292 log_error("Failed to issue method call: %s", strerror(-r));
296 r = sd_bus_message_read(reply, "s", &hello);
298 log_error("Failed to get string: %s", strerror(-r));
302 assert(streq(hello, "hello"));
304 if (pipe2(pp, O_CLOEXEC|O_NONBLOCK) < 0) {
305 log_error("Failed to allocate pipe: %m");
310 r = sd_bus_call_method(
312 "org.freedesktop.systemd.test",
314 "org.freedesktop.systemd.test",
321 log_error("Failed to issue method call: %s", strerror(-r));
326 if (read(pp[0], &x, 1) <= 0) {
327 log_error("Failed to read from pipe: %s", errno ? strerror(errno) : "early read");
335 _cleanup_bus_message_unref_ sd_bus_message *q;
337 r = sd_bus_message_new_method_call(
339 "org.freedesktop.systemd.test",
341 "org.freedesktop.systemd.test",
345 log_error("Failed to allocate method call: %s", strerror(-r));
347 sd_bus_send(bus, q, NULL);
353 sd_bus_error_free(&error);
357 return INT_TO_PTR(r);
360 static int quit_callback(sd_bus *b, sd_bus_message *m, void *userdata) {
363 log_error("Quit callback: %s", strerror(sd_bus_message_get_errno(m)));
369 static void* client2(void*p) {
370 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
372 sd_bus_error error = SD_BUS_ERROR_NULL;
377 r = sd_bus_open_user(&bus);
379 log_error("Failed to connect to user bus: %s", strerror(-r));
383 r = sd_bus_message_new_method_call(
385 "org.freedesktop.systemd.test",
386 "/foo/bar/waldo/piep",
391 log_error("Failed to allocate method call: %s", strerror(-r));
395 r = sd_bus_send(bus, m, NULL);
397 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
401 sd_bus_message_unref(m);
404 r = sd_bus_message_new_signal(
411 log_error("Failed to allocate signal: %s", strerror(-r));
415 r = sd_bus_send(bus, m, NULL);
417 log_error("Failed to issue signal: %s", bus_error_message(&error, -r));
421 sd_bus_message_unref(m);
424 r = sd_bus_message_new_method_call(
426 "org.freedesktop.systemd.test",
428 "org.freedesktop.DBus.Peer",
432 log_error("Failed to allocate method call: %s", strerror(-r));
436 r = sd_bus_send_with_reply_and_block(bus, m, 0, &error, &reply);
438 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
442 r = sd_bus_message_read(reply, "s", &mid);
444 log_error("Failed to parse machine ID: %s", strerror(-r));
448 log_info("Machine ID is %s.", mid);
450 sd_bus_message_unref(m);
453 r = sd_bus_message_new_method_call(
455 "org.freedesktop.systemd.test",
457 "org.freedesktop.systemd.test",
461 log_error("Failed to allocate method call: %s", strerror(-r));
465 sd_bus_message_unref(reply);
468 r = sd_bus_send_with_reply_and_block(bus, m, 200 * USEC_PER_MSEC, &error, &reply);
470 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
472 log_info("Slow call succeed.");
474 sd_bus_message_unref(m);
477 r = sd_bus_message_new_method_call(
479 "org.freedesktop.systemd.test",
481 "org.freedesktop.systemd.test",
485 log_error("Failed to allocate method call: %s", strerror(-r));
489 r = sd_bus_send_with_reply(bus, m, quit_callback, &quit, 200 * USEC_PER_MSEC, NULL);
491 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
496 r = sd_bus_process(bus, NULL);
498 log_error("Failed to process requests: %s", strerror(-r));
502 r = sd_bus_wait(bus, (uint64_t) -1);
504 log_error("Failed to wait: %s", strerror(-r));
514 _cleanup_bus_message_unref_ sd_bus_message *q;
516 r = sd_bus_message_new_method_call(
518 "org.freedesktop.systemd.test",
520 "org.freedesktop.systemd.test",
524 log_error("Failed to allocate method call: %s", strerror(-r));
528 sd_bus_send(bus, q, NULL);
533 sd_bus_error_free(&error);
534 return INT_TO_PTR(r);
537 int main(int argc, char *argv[]) {
543 r = server_init(&bus);
545 log_info("Failed to connect to bus, skipping tests.");
546 return EXIT_TEST_SKIP;
549 log_info("Initialized...");
551 r = pthread_create(&c1, NULL, client1, bus);
555 r = pthread_create(&c2, NULL, client2, bus);
561 q = pthread_join(c1, &p);
564 if (PTR_TO_INT(p) < 0)
567 q = pthread_join(c2, &p);
570 if (PTR_TO_INT(p) < 0)