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/>.
30 #include "formats-util.h"
33 #include "bus-error.h"
34 #include "bus-match.h"
35 #include "bus-internal.h"
38 static int match_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
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_message *m, void *userdata, sd_bus_error *ret_error) {
46 if (sd_bus_message_is_method_error(m, NULL))
49 if (sd_bus_message_is_method_call(m, "org.object.test", "Foobar")) {
50 log_info("Invoked Foobar() on %s", sd_bus_message_get_path(m));
52 r = sd_bus_reply_method_return(m, NULL);
54 return log_error_errno(r, "Failed to send reply: %m");
62 static int server_init(sd_bus **_bus) {
70 r = sd_bus_open_user(&bus);
72 log_error_errno(r, "Failed to connect to user bus: %m");
76 r = sd_bus_get_bus_id(bus, &id);
78 log_error_errno(r, "Failed to get server ID: %m");
82 r = sd_bus_get_unique_name(bus, &unique);
84 log_error_errno(r, "Failed to get unique name: %m");
88 log_info("Peer ID is " SD_ID128_FORMAT_STR ".", SD_ID128_FORMAT_VAL(id));
89 log_info("Unique ID: %s", unique);
90 log_info("Can send file handles: %i", sd_bus_can_send(bus, 'h'));
92 r = sd_bus_request_name(bus, "org.freedesktop.systemd.test", 0);
94 log_error_errno(r, "Failed to acquire name: %m");
98 r = sd_bus_add_fallback(bus, NULL, "/foo/bar", object_callback, NULL);
100 log_error_errno(r, "Failed to add object: %m");
104 r = sd_bus_add_match(bus, NULL, "type='signal',interface='foo.bar',member='Notify'", match_callback, NULL);
106 log_error_errno(r, "Failed to add match: %m");
110 r = sd_bus_add_match(bus, NULL, "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged'", match_callback, NULL);
112 log_error_errno(r, "Failed to add match: %m");
116 bus_match_dump(&bus->match_callbacks, 0);
128 static int server(sd_bus *bus) {
130 bool client1_gone = false, client2_gone = false;
132 while (!client1_gone || !client2_gone) {
133 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
135 const char *label = NULL;
137 r = sd_bus_process(bus, &m);
139 log_error_errno(r, "Failed to process requests: %m");
144 r = sd_bus_wait(bus, (uint64_t) -1);
146 log_error_errno(r, "Failed to wait: %m");
156 sd_bus_creds_get_pid(sd_bus_message_get_creds(m), &pid);
157 sd_bus_creds_get_selinux_context(sd_bus_message_get_creds(m), &label);
158 log_info("Got message! member=%s pid="PID_FMT" label=%s",
159 strna(sd_bus_message_get_member(m)),
162 /* bus_message_dump(m); */
163 /* sd_bus_message_rewind(m, true); */
165 if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "LowerCase")) {
167 _cleanup_free_ char *lowercase = NULL;
169 r = sd_bus_message_read(m, "s", &hello);
171 log_error_errno(r, "Failed to get parameter: %m");
175 lowercase = strdup(hello);
181 ascii_strlower(lowercase);
183 r = sd_bus_reply_method_return(m, "s", lowercase);
185 log_error_errno(r, "Failed to send reply: %m");
188 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient1")) {
190 r = sd_bus_reply_method_return(m, NULL);
192 log_error_errno(r, "Failed to send reply: %m");
197 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient2")) {
199 r = sd_bus_reply_method_return(m, NULL);
201 log_error_errno(r, "Failed to send reply: %m");
206 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Slow")) {
210 r = sd_bus_reply_method_return(m, NULL);
212 log_error_errno(r, "Failed to send reply: %m");
216 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "FileDescriptor")) {
218 static const char x = 'X';
220 r = sd_bus_message_read(m, "h", &fd);
222 log_error_errno(r, "Failed to get parameter: %m");
226 log_info("Received fd=%d", fd);
228 if (write(fd, &x, 1) < 0) {
229 log_error_errno(errno, "Failed to write to fd: %m");
234 r = sd_bus_reply_method_return(m, NULL);
236 log_error_errno(r, "Failed to send reply: %m");
240 } else if (sd_bus_message_is_method_call(m, NULL, NULL)) {
242 r = sd_bus_reply_method_error(
244 &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method."));
246 log_error_errno(r, "Failed to send reply: %m");
263 static void* client1(void*p) {
264 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
266 sd_bus_error error = SD_BUS_ERROR_NULL;
269 int pp[2] = { -1, -1 };
272 r = sd_bus_open_user(&bus);
274 log_error_errno(r, "Failed to connect to user bus: %m");
278 r = sd_bus_call_method(
280 "org.freedesktop.systemd.test",
282 "org.freedesktop.systemd.test",
289 log_error_errno(r, "Failed to issue method call: %m");
293 r = sd_bus_message_read(reply, "s", &hello);
295 log_error_errno(r, "Failed to get string: %m");
299 assert_se(streq(hello, "hello"));
301 if (pipe2(pp, O_CLOEXEC|O_NONBLOCK) < 0) {
302 log_error_errno(errno, "Failed to allocate pipe: %m");
307 log_info("Sending fd=%d", pp[1]);
309 r = sd_bus_call_method(
311 "org.freedesktop.systemd.test",
313 "org.freedesktop.systemd.test",
320 log_error_errno(r, "Failed to issue method call: %m");
325 if (read(pp[0], &x, 1) <= 0) {
326 log_error("Failed to read from pipe: %s", errno ? strerror(errno) : "early read");
334 _cleanup_bus_message_unref_ sd_bus_message *q;
336 r = sd_bus_message_new_method_call(
339 "org.freedesktop.systemd.test",
341 "org.freedesktop.systemd.test",
344 log_error_errno(r, "Failed to allocate method call: %m");
346 sd_bus_send(bus, q, NULL);
352 sd_bus_error_free(&error);
356 return INT_TO_PTR(r);
359 static int quit_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
362 log_error("Quit callback: %s", strerror(sd_bus_message_get_errno(m)));
368 static void* client2(void*p) {
369 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
371 sd_bus_error error = SD_BUS_ERROR_NULL;
376 r = sd_bus_open_user(&bus);
378 log_error_errno(r, "Failed to connect to user bus: %m");
382 r = sd_bus_message_new_method_call(
385 "org.freedesktop.systemd.test",
386 "/foo/bar/waldo/piep",
390 log_error_errno(r, "Failed to allocate method call: %m");
394 r = sd_bus_send(bus, m, NULL);
396 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
400 sd_bus_message_unref(m);
403 r = sd_bus_message_new_signal(
410 log_error_errno(r, "Failed to allocate signal: %m");
414 r = sd_bus_send(bus, m, NULL);
416 log_error("Failed to issue signal: %s", bus_error_message(&error, -r));
420 sd_bus_message_unref(m);
423 r = sd_bus_message_new_method_call(
426 "org.freedesktop.systemd.test",
428 "org.freedesktop.DBus.Peer",
431 log_error_errno(r, "Failed to allocate method call: %m");
435 r = sd_bus_call(bus, m, 0, &error, &reply);
437 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
441 r = sd_bus_message_read(reply, "s", &mid);
443 log_error_errno(r, "Failed to parse machine ID: %m");
447 log_info("Machine ID is %s.", mid);
449 sd_bus_message_unref(m);
452 r = sd_bus_message_new_method_call(
455 "org.freedesktop.systemd.test",
457 "org.freedesktop.systemd.test",
460 log_error_errno(r, "Failed to allocate method call: %m");
464 sd_bus_message_unref(reply);
467 r = sd_bus_call(bus, m, 200 * USEC_PER_MSEC, &error, &reply);
469 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
471 log_info("Slow call succeed.");
473 sd_bus_message_unref(m);
476 r = sd_bus_message_new_method_call(
479 "org.freedesktop.systemd.test",
481 "org.freedesktop.systemd.test",
484 log_error_errno(r, "Failed to allocate method call: %m");
488 r = sd_bus_call_async(bus, NULL, m, quit_callback, &quit, 200 * USEC_PER_MSEC);
490 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
495 r = sd_bus_process(bus, NULL);
497 log_error_errno(r, "Failed to process requests: %m");
501 r = sd_bus_wait(bus, (uint64_t) -1);
503 log_error_errno(r, "Failed to wait: %m");
513 _cleanup_bus_message_unref_ sd_bus_message *q;
515 r = sd_bus_message_new_method_call(
518 "org.freedesktop.systemd.test",
520 "org.freedesktop.systemd.test",
523 log_error_errno(r, "Failed to allocate method call: %m");
527 sd_bus_send(bus, q, NULL);
532 sd_bus_error_free(&error);
533 return INT_TO_PTR(r);
536 int main(int argc, char *argv[]) {
542 r = server_init(&bus);
544 log_info("Failed to connect to bus, skipping tests.");
545 return EXIT_TEST_SKIP;
548 log_info("Initialized...");
550 r = pthread_create(&c1, NULL, client1, bus);
554 r = pthread_create(&c2, NULL, client2, bus);
560 q = pthread_join(c1, &p);
563 if (PTR_TO_INT(p) < 0)
566 q = pthread_join(c2, &p);
569 if (PTR_TO_INT(p) < 0)