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;
265 _cleanup_bus_close_unref_ sd_bus *bus = NULL;
266 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
269 _cleanup_close_pair_ 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);
350 return INT_TO_PTR(r);
353 static int quit_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
356 log_error("Quit callback: %s", strerror(sd_bus_message_get_errno(m)));
362 static void* client2(void*p) {
363 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
364 _cleanup_bus_close_unref_ sd_bus *bus = NULL;
365 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
370 r = sd_bus_open_user(&bus);
372 log_error_errno(r, "Failed to connect to user bus: %m");
376 r = sd_bus_message_new_method_call(
379 "org.freedesktop.systemd.test",
380 "/foo/bar/waldo/piep",
384 log_error_errno(r, "Failed to allocate method call: %m");
388 r = sd_bus_send(bus, m, NULL);
390 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
394 m = sd_bus_message_unref(m);
396 r = sd_bus_message_new_signal(
403 log_error_errno(r, "Failed to allocate signal: %m");
407 r = sd_bus_send(bus, m, NULL);
409 log_error("Failed to issue signal: %s", bus_error_message(&error, -r));
413 m = sd_bus_message_unref(m);
415 r = sd_bus_message_new_method_call(
418 "org.freedesktop.systemd.test",
420 "org.freedesktop.DBus.Peer",
423 log_error_errno(r, "Failed to allocate method call: %m");
427 r = sd_bus_call(bus, m, 0, &error, &reply);
429 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
433 r = sd_bus_message_read(reply, "s", &mid);
435 log_error_errno(r, "Failed to parse machine ID: %m");
439 log_info("Machine ID is %s.", mid);
441 m = sd_bus_message_unref(m);
443 r = sd_bus_message_new_method_call(
446 "org.freedesktop.systemd.test",
448 "org.freedesktop.systemd.test",
451 log_error_errno(r, "Failed to allocate method call: %m");
455 reply = sd_bus_message_unref(reply);
457 r = sd_bus_call(bus, m, 200 * USEC_PER_MSEC, &error, &reply);
459 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
461 log_info("Slow call succeed.");
463 m = sd_bus_message_unref(m);
465 r = sd_bus_message_new_method_call(
468 "org.freedesktop.systemd.test",
470 "org.freedesktop.systemd.test",
473 log_error_errno(r, "Failed to allocate method call: %m");
477 r = sd_bus_call_async(bus, NULL, m, quit_callback, &quit, 200 * USEC_PER_MSEC);
479 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
484 r = sd_bus_process(bus, NULL);
486 log_error_errno(r, "Failed to process requests: %m");
490 r = sd_bus_wait(bus, (uint64_t) -1);
492 log_error_errno(r, "Failed to wait: %m");
502 _cleanup_bus_message_unref_ sd_bus_message *q;
504 r = sd_bus_message_new_method_call(
507 "org.freedesktop.systemd.test",
509 "org.freedesktop.systemd.test",
512 log_error_errno(r, "Failed to allocate method call: %m");
516 (void) sd_bus_send(bus, q, NULL);
519 return INT_TO_PTR(r);
522 int main(int argc, char *argv[]) {
528 r = server_init(&bus);
530 log_info("Failed to connect to bus, skipping tests.");
531 return EXIT_TEST_SKIP;
534 log_info("Initialized...");
536 r = pthread_create(&c1, NULL, client1, bus);
540 r = pthread_create(&c2, NULL, client2, bus);
546 q = pthread_join(c1, &p);
549 if (PTR_TO_INT(p) < 0)
552 q = pthread_join(c2, &p);
555 if (PTR_TO_INT(p) < 0)