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")) {
209 r = sd_bus_reply_method_return(bus, m, NULL);
211 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 close_nointr_nofail(fd);
235 r = sd_bus_reply_method_return(bus, m, NULL);
237 log_error("Failed to send reply: %s", strerror(-r));
241 } else if (sd_bus_message_is_method_call(m, NULL, NULL)) {
243 r = sd_bus_reply_method_error(
245 &SD_BUS_ERROR_MAKE("org.freedesktop.DBus.Error.UnknownMethod", "Unknown method."));
247 log_error("Failed to send reply: %s", strerror(-r));
264 static void* client1(void*p) {
265 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
267 sd_bus_error error = SD_BUS_ERROR_NULL;
270 int pp[2] = { -1, -1 };
273 r = sd_bus_open_user(&bus);
275 log_error("Failed to connect to user bus: %s", strerror(-r));
279 r = sd_bus_call_method(
281 "org.freedesktop.systemd.test",
283 "org.freedesktop.systemd.test",
290 log_error("Failed to issue method call: %s", strerror(-r));
294 r = sd_bus_message_read(reply, "s", &hello);
296 log_error("Failed to get string: %s", strerror(-r));
300 assert(streq(hello, "hello"));
302 if (pipe2(pp, O_CLOEXEC|O_NONBLOCK) < 0) {
303 log_error("Failed to allocate pipe: %m");
308 sd_bus_message_unref(m);
310 r = sd_bus_message_new_method_call(
312 "org.freedesktop.systemd.test",
314 "org.freedesktop.systemd.test",
318 log_error("Failed to allocate method call: %s", strerror(-r));
322 r = sd_bus_message_append(m, "h", pp[1]);
324 log_error("Failed to append string: %s", strerror(-r));
328 sd_bus_message_unref(reply);
330 r = sd_bus_send_with_reply_and_block(bus, m, 0, &error, &reply);
332 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
337 if (read(pp[0], &x, 1) <= 0) {
338 log_error("Failed to read from pipe: %s", errno ? strerror(errno) : "early read");
346 _cleanup_bus_message_unref_ sd_bus_message *q;
348 r = sd_bus_message_new_method_call(
350 "org.freedesktop.systemd.test",
352 "org.freedesktop.systemd.test",
356 log_error("Failed to allocate method call: %s", strerror(-r));
360 sd_bus_send(bus, q, NULL);
365 sd_bus_error_free(&error);
369 return INT_TO_PTR(r);
372 static int quit_callback(sd_bus *b, int ret, sd_bus_message *m, void *userdata) {
375 log_error("Quit callback: %s", strerror(ret));
381 static void* client2(void*p) {
382 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
384 sd_bus_error error = SD_BUS_ERROR_NULL;
389 r = sd_bus_open_user(&bus);
391 log_error("Failed to connect to user bus: %s", strerror(-r));
395 r = sd_bus_message_new_method_call(
397 "org.freedesktop.systemd.test",
398 "/foo/bar/waldo/piep",
403 log_error("Failed to allocate method call: %s", strerror(-r));
407 r = sd_bus_send(bus, m, NULL);
409 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
413 sd_bus_message_unref(m);
416 r = sd_bus_message_new_signal(
423 log_error("Failed to allocate signal: %s", strerror(-r));
427 r = sd_bus_send(bus, m, NULL);
429 log_error("Failed to issue signal: %s", bus_error_message(&error, -r));
433 sd_bus_message_unref(m);
436 r = sd_bus_message_new_method_call(
438 "org.freedesktop.systemd.test",
440 "org.freedesktop.DBus.Peer",
444 log_error("Failed to allocate method call: %s", strerror(-r));
448 r = sd_bus_send_with_reply_and_block(bus, m, 0, &error, &reply);
450 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
454 r = sd_bus_message_read(reply, "s", &mid);
456 log_error("Failed to parse machine ID: %s", strerror(-r));
460 log_info("Machine ID is %s.", mid);
462 sd_bus_message_unref(m);
465 r = sd_bus_message_new_method_call(
467 "org.freedesktop.systemd.test",
469 "org.freedesktop.systemd.test",
473 log_error("Failed to allocate method call: %s", strerror(-r));
477 sd_bus_message_unref(reply);
480 r = sd_bus_send_with_reply_and_block(bus, m, 200 * USEC_PER_MSEC, &error, &reply);
482 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
484 log_info("Slow call succeed.");
486 sd_bus_message_unref(m);
489 r = sd_bus_message_new_method_call(
491 "org.freedesktop.systemd.test",
493 "org.freedesktop.systemd.test",
497 log_error("Failed to allocate method call: %s", strerror(-r));
501 r = sd_bus_send_with_reply(bus, m, quit_callback, &quit, 200 * USEC_PER_MSEC, NULL);
503 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
508 r = sd_bus_process(bus, NULL);
510 log_error("Failed to process requests: %s", strerror(-r));
514 r = sd_bus_wait(bus, (uint64_t) -1);
516 log_error("Failed to wait: %s", strerror(-r));
526 _cleanup_bus_message_unref_ sd_bus_message *q;
528 r = sd_bus_message_new_method_call(
530 "org.freedesktop.systemd.test",
532 "org.freedesktop.systemd.test",
536 log_error("Failed to allocate method call: %s", strerror(-r));
540 sd_bus_send(bus, q, NULL);
545 sd_bus_error_free(&error);
546 return INT_TO_PTR(r);
549 int main(int argc, char *argv[]) {
555 r = server_init(&bus);
557 log_info("Failed to connect to bus, skipping tests.");
558 return EXIT_TEST_SKIP;
561 log_info("Initialized...");
563 r = pthread_create(&c1, NULL, client1, bus);
567 r = pthread_create(&c2, NULL, client2, bus);
573 q = pthread_join(c1, &p);
576 if (PTR_TO_INT(p) < 0)
579 q = pthread_join(c2, &p);
582 if (PTR_TO_INT(p) < 0)