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_message_new_method_return(bus, m, &reply);
58 log_error("Failed to allocate return: %s", strerror(-r));
62 r = sd_bus_send(bus, reply, NULL);
64 log_error("Failed to send reply: %s", strerror(-r));
74 static int server_init(sd_bus **_bus) {
82 r = sd_bus_open_user(&bus);
84 log_error("Failed to connect to user bus: %s", strerror(-r));
88 r = sd_bus_get_server_id(bus, &id);
90 log_error("Failed to get server ID: %s", strerror(-r));
94 r = sd_bus_get_unique_name(bus, &unique);
96 log_error("Failed to get unique name: %s", strerror(-r));
100 log_info("Peer ID is " SD_ID128_FORMAT_STR ".", SD_ID128_FORMAT_VAL(id));
101 log_info("Unique ID: %s", unique);
102 log_info("Can send file handles: %i", sd_bus_can_send(bus, 'h'));
104 r = sd_bus_request_name(bus, "org.freedesktop.systemd.test", 0);
106 log_error("Failed to acquire name: %s", strerror(-r));
110 r = sd_bus_add_fallback(bus, "/foo/bar", object_callback, NULL);
112 log_error("Failed to add object: %s", strerror(-r));
116 r = sd_bus_add_match(bus, "type='signal',interface='foo.bar',member='Notify'", match_callback, NULL);
118 log_error("Failed to add match: %s", strerror(-r));
122 r = sd_bus_add_match(bus, "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged'", match_callback, NULL);
124 log_error("Failed to add match: %s", strerror(-r));
128 bus_match_dump(&bus->match_callbacks, 0);
140 static int server(sd_bus *bus) {
142 bool client1_gone = false, client2_gone = false;
144 while (!client1_gone || !client2_gone) {
145 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
148 r = sd_bus_process(bus, &m);
150 log_error("Failed to process requests: %s", strerror(-r));
155 r = sd_bus_wait(bus, (uint64_t) -1);
157 log_error("Failed to wait: %s", strerror(-r));
167 sd_bus_message_get_pid(m, &pid);
168 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)));
169 /* bus_message_dump(m); */
170 /* sd_bus_message_rewind(m, true); */
172 if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "LowerCase")) {
174 _cleanup_free_ char *lowercase = NULL;
176 r = sd_bus_message_read(m, "s", &hello);
178 log_error("Failed to get parameter: %s", strerror(-r));
182 r = sd_bus_message_new_method_return(bus, m, &reply);
184 log_error("Failed to allocate return: %s", strerror(-r));
188 lowercase = strdup(hello);
194 ascii_strlower(lowercase);
196 r = sd_bus_message_append(reply, "s", lowercase);
198 log_error("Failed to append message: %s", strerror(-r));
201 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient1")) {
203 r = sd_bus_message_new_method_return(bus, m, &reply);
205 log_error("Failed to allocate return: %s", strerror(-r));
210 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient2")) {
212 r = sd_bus_message_new_method_return(bus, m, &reply);
214 log_error("Failed to allocate return: %s", strerror(-r));
219 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Slow")) {
221 r = sd_bus_message_new_method_return(bus, m, &reply);
223 log_error("Failed to allocate return: %s", strerror(-r));
229 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "FileDescriptor")) {
231 static const char x = 'X';
233 r = sd_bus_message_read(m, "h", &fd);
235 log_error("Failed to get parameter: %s", strerror(-r));
239 if (write(fd, &x, 1) < 0) {
240 log_error("Failed to write to fd: %m");
241 close_nointr_nofail(fd);
245 close_nointr_nofail(fd);
247 r = sd_bus_message_new_method_return(bus, m, &reply);
249 log_error("Failed to allocate return: %s", strerror(-r));
253 } else if (sd_bus_message_is_method_call(m, NULL, NULL)) {
254 const sd_bus_error e = SD_BUS_ERROR_INIT_CONST("org.freedesktop.DBus.Error.UnknownMethod", "Unknown method.");
256 r = sd_bus_message_new_method_error(bus, m, &e, &reply);
258 log_error("Failed to allocate return: %s", strerror(-r));
264 r = sd_bus_send(bus, reply, NULL);
266 log_error("Failed to send reply: %s", strerror(-r));
270 /* log_info("Sent"); */
271 /* bus_message_dump(reply); */
272 /* sd_bus_message_rewind(reply, true); */
287 static void* client1(void*p) {
288 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
290 sd_bus_error error = SD_BUS_ERROR_INIT;
293 int pp[2] = { -1, -1 };
296 r = sd_bus_open_user(&bus);
298 log_error("Failed to connect to user bus: %s", strerror(-r));
302 r = sd_bus_message_new_method_call(
304 "org.freedesktop.systemd.test",
306 "org.freedesktop.systemd.test",
310 log_error("Failed to allocate method call: %s", strerror(-r));
314 r = sd_bus_message_append(m, "s", "HELLO");
316 log_error("Failed to append string: %s", strerror(-r));
320 r = sd_bus_send_with_reply_and_block(bus, m, 0, &error, &reply);
322 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
326 r = sd_bus_message_read(reply, "s", &hello);
328 log_error("Failed to get string: %s", strerror(-r));
332 assert(streq(hello, "hello"));
334 if (pipe2(pp, O_CLOEXEC|O_NONBLOCK) < 0) {
335 log_error("Failed to allocate pipe: %m");
340 sd_bus_message_unref(m);
342 r = sd_bus_message_new_method_call(
344 "org.freedesktop.systemd.test",
346 "org.freedesktop.systemd.test",
350 log_error("Failed to allocate method call: %s", strerror(-r));
354 r = sd_bus_message_append(m, "h", pp[1]);
356 log_error("Failed to append string: %s", strerror(-r));
360 sd_bus_message_unref(reply);
362 r = sd_bus_send_with_reply_and_block(bus, m, 0, &error, &reply);
364 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
369 if (read(pp[0], &x, 1) <= 0) {
370 log_error("Failed to read from pipe: %s", errno ? strerror(errno) : "early read");
378 _cleanup_bus_message_unref_ sd_bus_message *q;
380 r = sd_bus_message_new_method_call(
382 "org.freedesktop.systemd.test",
384 "org.freedesktop.systemd.test",
388 log_error("Failed to allocate method call: %s", strerror(-r));
392 sd_bus_send(bus, q, NULL);
397 sd_bus_error_free(&error);
401 return INT_TO_PTR(r);
404 static int quit_callback(sd_bus *b, int ret, sd_bus_message *m, void *userdata) {
407 log_error("Quit callback: %s", strerror(ret));
413 static void* client2(void*p) {
414 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
416 sd_bus_error error = SD_BUS_ERROR_INIT;
421 r = sd_bus_open_user(&bus);
423 log_error("Failed to connect to user bus: %s", strerror(-r));
427 r = sd_bus_message_new_method_call(
429 "org.freedesktop.systemd.test",
430 "/foo/bar/waldo/piep",
435 log_error("Failed to allocate method call: %s", strerror(-r));
439 r = sd_bus_send(bus, m, NULL);
441 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
445 sd_bus_message_unref(m);
448 r = sd_bus_message_new_signal(
455 log_error("Failed to allocate signal: %s", strerror(-r));
459 r = sd_bus_send(bus, m, NULL);
461 log_error("Failed to issue signal: %s", bus_error_message(&error, -r));
465 sd_bus_message_unref(m);
468 r = sd_bus_message_new_method_call(
470 "org.freedesktop.systemd.test",
472 "org.freedesktop.DBus.Peer",
476 log_error("Failed to allocate method call: %s", strerror(-r));
480 r = sd_bus_send_with_reply_and_block(bus, m, 0, &error, &reply);
482 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
486 r = sd_bus_message_read(reply, "s", &mid);
488 log_error("Failed to parse machine ID: %s", strerror(-r));
492 log_info("Machine ID is %s.", mid);
494 sd_bus_message_unref(m);
497 r = sd_bus_message_new_method_call(
499 "org.freedesktop.systemd.test",
501 "org.freedesktop.systemd.test",
505 log_error("Failed to allocate method call: %s", strerror(-r));
509 sd_bus_message_unref(reply);
512 r = sd_bus_send_with_reply_and_block(bus, m, 200 * USEC_PER_MSEC, &error, &reply);
514 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
516 log_info("Slow call succeed.");
518 sd_bus_message_unref(m);
521 r = sd_bus_message_new_method_call(
523 "org.freedesktop.systemd.test",
525 "org.freedesktop.systemd.test",
529 log_error("Failed to allocate method call: %s", strerror(-r));
533 r = sd_bus_send_with_reply(bus, m, quit_callback, &quit, 200 * USEC_PER_MSEC, NULL);
535 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
540 r = sd_bus_process(bus, NULL);
542 log_error("Failed to process requests: %s", strerror(-r));
546 r = sd_bus_wait(bus, (uint64_t) -1);
548 log_error("Failed to wait: %s", strerror(-r));
558 _cleanup_bus_message_unref_ sd_bus_message *q;
560 r = sd_bus_message_new_method_call(
562 "org.freedesktop.systemd.test",
564 "org.freedesktop.systemd.test",
568 log_error("Failed to allocate method call: %s", strerror(-r));
572 sd_bus_send(bus, q, NULL);
577 sd_bus_error_free(&error);
578 return INT_TO_PTR(r);
581 int main(int argc, char *argv[]) {
587 r = server_init(&bus);
589 log_info("Failed to connect to bus, skipping tests.");
590 return EXIT_TEST_SKIP;
593 log_info("Initialized...");
595 r = pthread_create(&c1, NULL, client1, bus);
599 r = pthread_create(&c2, NULL, client2, bus);
605 q = pthread_join(c1, &p);
608 if (PTR_TO_INT(p) < 0)
611 q = pthread_join(c2, &p);
614 if (PTR_TO_INT(p) < 0)