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, sd_bus_error *ret_error) {
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, sd_bus_error *ret_error) {
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(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, NULL, "/foo/bar", object_callback, NULL);
105 log_error("Failed to add object: %s", strerror(-r));
109 r = sd_bus_add_match(bus, NULL, "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, NULL, "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_creds_get_pid(sd_bus_message_get_creds(m), &pid);
162 sd_bus_creds_get_selinux_context(sd_bus_message_get_creds(m), &label);
163 log_info("Got message! member=%s pid="PID_FMT" 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(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(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(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(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 log_info("Received fd=%d", fd);
233 if (write(fd, &x, 1) < 0) {
234 log_error("Failed to write to fd: %m");
239 r = sd_bus_reply_method_return(m, NULL);
241 log_error("Failed to send reply: %s", strerror(-r));
245 } else if (sd_bus_message_is_method_call(m, NULL, NULL)) {
247 r = sd_bus_reply_method_error(
249 &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method."));
251 log_error("Failed to send reply: %s", strerror(-r));
268 static void* client1(void*p) {
269 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
271 sd_bus_error error = SD_BUS_ERROR_NULL;
274 int pp[2] = { -1, -1 };
277 r = sd_bus_open_user(&bus);
279 log_error("Failed to connect to user bus: %s", strerror(-r));
283 r = sd_bus_call_method(
285 "org.freedesktop.systemd.test",
287 "org.freedesktop.systemd.test",
294 log_error("Failed to issue method call: %s", strerror(-r));
298 r = sd_bus_message_read(reply, "s", &hello);
300 log_error("Failed to get string: %s", strerror(-r));
304 assert(streq(hello, "hello"));
306 if (pipe2(pp, O_CLOEXEC|O_NONBLOCK) < 0) {
307 log_error("Failed to allocate pipe: %m");
312 log_info("Sending fd=%d", pp[1]);
314 r = sd_bus_call_method(
316 "org.freedesktop.systemd.test",
318 "org.freedesktop.systemd.test",
325 log_error("Failed to issue method call: %s", strerror(-r));
330 if (read(pp[0], &x, 1) <= 0) {
331 log_error("Failed to read from pipe: %s", errno ? strerror(errno) : "early read");
339 _cleanup_bus_message_unref_ sd_bus_message *q;
341 r = sd_bus_message_new_method_call(
344 "org.freedesktop.systemd.test",
346 "org.freedesktop.systemd.test",
349 log_error("Failed to allocate method call: %s", strerror(-r));
351 sd_bus_send(bus, q, NULL);
357 sd_bus_error_free(&error);
361 return INT_TO_PTR(r);
364 static int quit_callback(sd_bus *b, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
367 log_error("Quit callback: %s", strerror(sd_bus_message_get_errno(m)));
373 static void* client2(void*p) {
374 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
376 sd_bus_error error = SD_BUS_ERROR_NULL;
381 r = sd_bus_open_user(&bus);
383 log_error("Failed to connect to user bus: %s", strerror(-r));
387 r = sd_bus_message_new_method_call(
390 "org.freedesktop.systemd.test",
391 "/foo/bar/waldo/piep",
395 log_error("Failed to allocate method call: %s", strerror(-r));
399 r = sd_bus_send(bus, m, NULL);
401 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
405 sd_bus_message_unref(m);
408 r = sd_bus_message_new_signal(
415 log_error("Failed to allocate signal: %s", strerror(-r));
419 r = sd_bus_send(bus, m, NULL);
421 log_error("Failed to issue signal: %s", bus_error_message(&error, -r));
425 sd_bus_message_unref(m);
428 r = sd_bus_message_new_method_call(
431 "org.freedesktop.systemd.test",
433 "org.freedesktop.DBus.Peer",
436 log_error("Failed to allocate method call: %s", strerror(-r));
440 r = sd_bus_call(bus, m, 0, &error, &reply);
442 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
446 r = sd_bus_message_read(reply, "s", &mid);
448 log_error("Failed to parse machine ID: %s", strerror(-r));
452 log_info("Machine ID is %s.", mid);
454 sd_bus_message_unref(m);
457 r = sd_bus_message_new_method_call(
460 "org.freedesktop.systemd.test",
462 "org.freedesktop.systemd.test",
465 log_error("Failed to allocate method call: %s", strerror(-r));
469 sd_bus_message_unref(reply);
472 r = sd_bus_call(bus, m, 200 * USEC_PER_MSEC, &error, &reply);
474 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
476 log_info("Slow call succeed.");
478 sd_bus_message_unref(m);
481 r = sd_bus_message_new_method_call(
484 "org.freedesktop.systemd.test",
486 "org.freedesktop.systemd.test",
489 log_error("Failed to allocate method call: %s", strerror(-r));
493 r = sd_bus_call_async(bus, NULL, m, quit_callback, &quit, 200 * USEC_PER_MSEC);
495 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
500 r = sd_bus_process(bus, NULL);
502 log_error("Failed to process requests: %s", strerror(-r));
506 r = sd_bus_wait(bus, (uint64_t) -1);
508 log_error("Failed to wait: %s", strerror(-r));
518 _cleanup_bus_message_unref_ sd_bus_message *q;
520 r = sd_bus_message_new_method_call(
523 "org.freedesktop.systemd.test",
525 "org.freedesktop.systemd.test",
528 log_error("Failed to allocate method call: %s", strerror(-r));
532 sd_bus_send(bus, q, NULL);
537 sd_bus_error_free(&error);
538 return INT_TO_PTR(r);
541 int main(int argc, char *argv[]) {
547 r = server_init(&bus);
549 log_info("Failed to connect to bus, skipping tests.");
550 return EXIT_TEST_SKIP;
553 log_info("Initialized...");
555 r = pthread_create(&c1, NULL, client1, bus);
559 r = pthread_create(&c2, NULL, client2, bus);
565 q = pthread_join(c1, &p);
568 if (PTR_TO_INT(p) < 0)
571 q = pthread_join(c2, &p);
574 if (PTR_TO_INT(p) < 0)