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)) {
255 r = sd_bus_message_new_method_error(
257 &SD_BUS_ERROR_MAKE("org.freedesktop.DBus.Error.UnknownMethod", "Unknown method."),
260 log_error("Failed to allocate return: %s", strerror(-r));
266 r = sd_bus_send(bus, reply, NULL);
268 log_error("Failed to send reply: %s", strerror(-r));
272 /* log_info("Sent"); */
273 /* bus_message_dump(reply); */
274 /* sd_bus_message_rewind(reply, true); */
289 static void* client1(void*p) {
290 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
292 sd_bus_error error = SD_BUS_ERROR_NULL;
295 int pp[2] = { -1, -1 };
298 r = sd_bus_open_user(&bus);
300 log_error("Failed to connect to user bus: %s", strerror(-r));
304 r = sd_bus_message_new_method_call(
306 "org.freedesktop.systemd.test",
308 "org.freedesktop.systemd.test",
312 log_error("Failed to allocate method call: %s", strerror(-r));
316 r = sd_bus_message_append(m, "s", "HELLO");
318 log_error("Failed to append string: %s", strerror(-r));
322 r = sd_bus_send_with_reply_and_block(bus, m, 0, &error, &reply);
324 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
328 r = sd_bus_message_read(reply, "s", &hello);
330 log_error("Failed to get string: %s", strerror(-r));
334 assert(streq(hello, "hello"));
336 if (pipe2(pp, O_CLOEXEC|O_NONBLOCK) < 0) {
337 log_error("Failed to allocate pipe: %m");
342 sd_bus_message_unref(m);
344 r = sd_bus_message_new_method_call(
346 "org.freedesktop.systemd.test",
348 "org.freedesktop.systemd.test",
352 log_error("Failed to allocate method call: %s", strerror(-r));
356 r = sd_bus_message_append(m, "h", pp[1]);
358 log_error("Failed to append string: %s", strerror(-r));
362 sd_bus_message_unref(reply);
364 r = sd_bus_send_with_reply_and_block(bus, m, 0, &error, &reply);
366 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
371 if (read(pp[0], &x, 1) <= 0) {
372 log_error("Failed to read from pipe: %s", errno ? strerror(errno) : "early read");
380 _cleanup_bus_message_unref_ sd_bus_message *q;
382 r = sd_bus_message_new_method_call(
384 "org.freedesktop.systemd.test",
386 "org.freedesktop.systemd.test",
390 log_error("Failed to allocate method call: %s", strerror(-r));
394 sd_bus_send(bus, q, NULL);
399 sd_bus_error_free(&error);
403 return INT_TO_PTR(r);
406 static int quit_callback(sd_bus *b, int ret, sd_bus_message *m, void *userdata) {
409 log_error("Quit callback: %s", strerror(ret));
415 static void* client2(void*p) {
416 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
418 sd_bus_error error = SD_BUS_ERROR_NULL;
423 r = sd_bus_open_user(&bus);
425 log_error("Failed to connect to user bus: %s", strerror(-r));
429 r = sd_bus_message_new_method_call(
431 "org.freedesktop.systemd.test",
432 "/foo/bar/waldo/piep",
437 log_error("Failed to allocate method call: %s", strerror(-r));
441 r = sd_bus_send(bus, m, NULL);
443 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
447 sd_bus_message_unref(m);
450 r = sd_bus_message_new_signal(
457 log_error("Failed to allocate signal: %s", strerror(-r));
461 r = sd_bus_send(bus, m, NULL);
463 log_error("Failed to issue signal: %s", bus_error_message(&error, -r));
467 sd_bus_message_unref(m);
470 r = sd_bus_message_new_method_call(
472 "org.freedesktop.systemd.test",
474 "org.freedesktop.DBus.Peer",
478 log_error("Failed to allocate method call: %s", strerror(-r));
482 r = sd_bus_send_with_reply_and_block(bus, m, 0, &error, &reply);
484 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
488 r = sd_bus_message_read(reply, "s", &mid);
490 log_error("Failed to parse machine ID: %s", strerror(-r));
494 log_info("Machine ID is %s.", mid);
496 sd_bus_message_unref(m);
499 r = sd_bus_message_new_method_call(
501 "org.freedesktop.systemd.test",
503 "org.freedesktop.systemd.test",
507 log_error("Failed to allocate method call: %s", strerror(-r));
511 sd_bus_message_unref(reply);
514 r = sd_bus_send_with_reply_and_block(bus, m, 200 * USEC_PER_MSEC, &error, &reply);
516 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
518 log_info("Slow call succeed.");
520 sd_bus_message_unref(m);
523 r = sd_bus_message_new_method_call(
525 "org.freedesktop.systemd.test",
527 "org.freedesktop.systemd.test",
531 log_error("Failed to allocate method call: %s", strerror(-r));
535 r = sd_bus_send_with_reply(bus, m, quit_callback, &quit, 200 * USEC_PER_MSEC, NULL);
537 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
542 r = sd_bus_process(bus, NULL);
544 log_error("Failed to process requests: %s", strerror(-r));
548 r = sd_bus_wait(bus, (uint64_t) -1);
550 log_error("Failed to wait: %s", strerror(-r));
560 _cleanup_bus_message_unref_ sd_bus_message *q;
562 r = sd_bus_message_new_method_call(
564 "org.freedesktop.systemd.test",
566 "org.freedesktop.systemd.test",
570 log_error("Failed to allocate method call: %s", strerror(-r));
574 sd_bus_send(bus, q, NULL);
579 sd_bus_error_free(&error);
580 return INT_TO_PTR(r);
583 int main(int argc, char *argv[]) {
589 r = server_init(&bus);
591 log_info("Failed to connect to bus, skipping tests.");
592 return EXIT_TEST_SKIP;
595 log_info("Initialized...");
597 r = pthread_create(&c1, NULL, client1, bus);
601 r = pthread_create(&c2, NULL, client2, bus);
607 q = pthread_join(c1, &p);
610 if (PTR_TO_INT(p) < 0)
613 q = pthread_join(c2, &p);
616 if (PTR_TO_INT(p) < 0)