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 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;
140 r = sd_bus_process(bus, &m);
142 log_error("Failed to process requests: %s", strerror(-r));
147 r = sd_bus_wait(bus, (uint64_t) -1);
149 log_error("Failed to wait: %s", strerror(-r));
159 sd_bus_message_get_pid(m, &pid);
160 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_selinux_context(m)));
161 /* bus_message_dump(m); */
162 /* sd_bus_message_rewind(m, true); */
164 if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "LowerCase")) {
166 _cleanup_free_ char *lowercase = NULL;
168 r = sd_bus_message_read(m, "s", &hello);
170 log_error("Failed to get parameter: %s", strerror(-r));
174 lowercase = strdup(hello);
180 ascii_strlower(lowercase);
182 r = sd_bus_reply_method_return(bus, m, "s", lowercase);
184 log_error("Failed to send reply: %s", strerror(-r));
187 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient1")) {
189 r = sd_bus_reply_method_return(bus, m, NULL);
191 log_error("Failed to send reply: %s", strerror(-r));
196 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient2")) {
198 r = sd_bus_reply_method_return(bus, m, NULL);
200 log_error("Failed to send reply: %s", strerror(-r));
205 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Slow")) {
209 r = sd_bus_reply_method_return(bus, m, NULL);
211 log_error("Failed to send reply: %s", strerror(-r));
215 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "FileDescriptor")) {
217 static const char x = 'X';
219 r = sd_bus_message_read(m, "h", &fd);
221 log_error("Failed to get parameter: %s", strerror(-r));
225 if (write(fd, &x, 1) < 0) {
226 log_error("Failed to write to fd: %m");
227 close_nointr_nofail(fd);
231 r = sd_bus_reply_method_return(bus, m, NULL);
233 log_error("Failed to send reply: %s", strerror(-r));
237 } else if (sd_bus_message_is_method_call(m, NULL, NULL)) {
239 r = sd_bus_reply_method_error(
241 &SD_BUS_ERROR_MAKE("org.freedesktop.DBus.Error.UnknownMethod", "Unknown method."));
243 log_error("Failed to send reply: %s", strerror(-r));
260 static void* client1(void*p) {
261 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
263 sd_bus_error error = SD_BUS_ERROR_NULL;
266 int pp[2] = { -1, -1 };
269 r = sd_bus_open_user(&bus);
271 log_error("Failed to connect to user bus: %s", strerror(-r));
275 r = sd_bus_call_method(
277 "org.freedesktop.systemd.test",
279 "org.freedesktop.systemd.test",
286 log_error("Failed to issue method call: %s", strerror(-r));
290 r = sd_bus_message_read(reply, "s", &hello);
292 log_error("Failed to get string: %s", strerror(-r));
296 assert(streq(hello, "hello"));
298 if (pipe2(pp, O_CLOEXEC|O_NONBLOCK) < 0) {
299 log_error("Failed to allocate pipe: %m");
304 r = sd_bus_call_method(
306 "org.freedesktop.systemd.test",
308 "org.freedesktop.systemd.test",
315 log_error("Failed to issue method call: %s", strerror(-r));
320 if (read(pp[0], &x, 1) <= 0) {
321 log_error("Failed to read from pipe: %s", errno ? strerror(errno) : "early read");
329 _cleanup_bus_message_unref_ sd_bus_message *q;
331 r = sd_bus_message_new_method_call(
333 "org.freedesktop.systemd.test",
335 "org.freedesktop.systemd.test",
339 log_error("Failed to allocate method call: %s", strerror(-r));
341 sd_bus_send(bus, q, NULL);
347 sd_bus_error_free(&error);
351 return INT_TO_PTR(r);
354 static int quit_callback(sd_bus *b, int ret, sd_bus_message *m, void *userdata) {
357 log_error("Quit callback: %s", strerror(ret));
363 static void* client2(void*p) {
364 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
366 sd_bus_error error = SD_BUS_ERROR_NULL;
371 r = sd_bus_open_user(&bus);
373 log_error("Failed to connect to user bus: %s", strerror(-r));
377 r = sd_bus_message_new_method_call(
379 "org.freedesktop.systemd.test",
380 "/foo/bar/waldo/piep",
385 log_error("Failed to allocate method call: %s", strerror(-r));
389 r = sd_bus_send(bus, m, NULL);
391 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
395 sd_bus_message_unref(m);
398 r = sd_bus_message_new_signal(
405 log_error("Failed to allocate signal: %s", strerror(-r));
409 r = sd_bus_send(bus, m, NULL);
411 log_error("Failed to issue signal: %s", bus_error_message(&error, -r));
415 sd_bus_message_unref(m);
418 r = sd_bus_message_new_method_call(
420 "org.freedesktop.systemd.test",
422 "org.freedesktop.DBus.Peer",
426 log_error("Failed to allocate method call: %s", strerror(-r));
430 r = sd_bus_send_with_reply_and_block(bus, m, 0, &error, &reply);
432 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
436 r = sd_bus_message_read(reply, "s", &mid);
438 log_error("Failed to parse machine ID: %s", strerror(-r));
442 log_info("Machine ID is %s.", mid);
444 sd_bus_message_unref(m);
447 r = sd_bus_message_new_method_call(
449 "org.freedesktop.systemd.test",
451 "org.freedesktop.systemd.test",
455 log_error("Failed to allocate method call: %s", strerror(-r));
459 sd_bus_message_unref(reply);
462 r = sd_bus_send_with_reply_and_block(bus, m, 200 * USEC_PER_MSEC, &error, &reply);
464 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
466 log_info("Slow call succeed.");
468 sd_bus_message_unref(m);
471 r = sd_bus_message_new_method_call(
473 "org.freedesktop.systemd.test",
475 "org.freedesktop.systemd.test",
479 log_error("Failed to allocate method call: %s", strerror(-r));
483 r = sd_bus_send_with_reply(bus, m, quit_callback, &quit, 200 * USEC_PER_MSEC, NULL);
485 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
490 r = sd_bus_process(bus, NULL);
492 log_error("Failed to process requests: %s", strerror(-r));
496 r = sd_bus_wait(bus, (uint64_t) -1);
498 log_error("Failed to wait: %s", strerror(-r));
508 _cleanup_bus_message_unref_ sd_bus_message *q;
510 r = sd_bus_message_new_method_call(
512 "org.freedesktop.systemd.test",
514 "org.freedesktop.systemd.test",
518 log_error("Failed to allocate method call: %s", strerror(-r));
522 sd_bus_send(bus, q, NULL);
527 sd_bus_error_free(&error);
528 return INT_TO_PTR(r);
531 int main(int argc, char *argv[]) {
537 r = server_init(&bus);
539 log_info("Failed to connect to bus, skipping tests.");
540 return EXIT_TEST_SKIP;
543 log_info("Initialized...");
545 r = pthread_create(&c1, NULL, client1, bus);
549 r = pthread_create(&c2, NULL, client2, bus);
555 q = pthread_join(c1, &p);
558 if (PTR_TO_INT(p) < 0)
561 q = pthread_join(c2, &p);
564 if (PTR_TO_INT(p) < 0)