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 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);
350 sd_bus_error_free(&error);
354 return INT_TO_PTR(r);
357 static int quit_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
360 log_error("Quit callback: %s", strerror(sd_bus_message_get_errno(m)));
366 static void* client2(void*p) {
367 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
369 sd_bus_error error = SD_BUS_ERROR_NULL;
374 r = sd_bus_open_user(&bus);
376 log_error_errno(r, "Failed to connect to user bus: %m");
380 r = sd_bus_message_new_method_call(
383 "org.freedesktop.systemd.test",
384 "/foo/bar/waldo/piep",
388 log_error_errno(r, "Failed to allocate method call: %m");
392 r = sd_bus_send(bus, m, NULL);
394 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
398 sd_bus_message_unref(m);
401 r = sd_bus_message_new_signal(
408 log_error_errno(r, "Failed to allocate signal: %m");
412 r = sd_bus_send(bus, m, NULL);
414 log_error("Failed to issue signal: %s", bus_error_message(&error, -r));
418 sd_bus_message_unref(m);
421 r = sd_bus_message_new_method_call(
424 "org.freedesktop.systemd.test",
426 "org.freedesktop.DBus.Peer",
429 log_error_errno(r, "Failed to allocate method call: %m");
433 r = sd_bus_call(bus, m, 0, &error, &reply);
435 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
439 r = sd_bus_message_read(reply, "s", &mid);
441 log_error_errno(r, "Failed to parse machine ID: %m");
445 log_info("Machine ID is %s.", mid);
447 sd_bus_message_unref(m);
450 r = sd_bus_message_new_method_call(
453 "org.freedesktop.systemd.test",
455 "org.freedesktop.systemd.test",
458 log_error_errno(r, "Failed to allocate method call: %m");
462 sd_bus_message_unref(reply);
465 r = sd_bus_call(bus, m, 200 * USEC_PER_MSEC, &error, &reply);
467 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
469 log_info("Slow call succeed.");
471 sd_bus_message_unref(m);
474 r = sd_bus_message_new_method_call(
477 "org.freedesktop.systemd.test",
479 "org.freedesktop.systemd.test",
482 log_error_errno(r, "Failed to allocate method call: %m");
486 r = sd_bus_call_async(bus, NULL, m, quit_callback, &quit, 200 * USEC_PER_MSEC);
488 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
493 r = sd_bus_process(bus, NULL);
495 log_error_errno(r, "Failed to process requests: %m");
499 r = sd_bus_wait(bus, (uint64_t) -1);
501 log_error_errno(r, "Failed to wait: %m");
511 _cleanup_bus_message_unref_ sd_bus_message *q;
513 r = sd_bus_message_new_method_call(
516 "org.freedesktop.systemd.test",
518 "org.freedesktop.systemd.test",
521 log_error_errno(r, "Failed to allocate method call: %m");
525 sd_bus_send(bus, q, NULL);
530 sd_bus_error_free(&error);
531 return INT_TO_PTR(r);
534 int main(int argc, char *argv[]) {
540 r = server_init(&bus);
542 log_info("Failed to connect to bus, skipping tests.");
543 return EXIT_TEST_SKIP;
546 log_info("Initialized...");
548 r = pthread_create(&c1, NULL, client1, bus);
552 r = pthread_create(&c2, NULL, client2, bus);
558 q = pthread_join(c1, &p);
561 if (PTR_TO_INT(p) < 0)
564 q = pthread_join(c2, &p);
567 if (PTR_TO_INT(p) < 0)