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/>.
32 #include "bus-error.h"
33 #include "bus-match.h"
34 #include "bus-internal.h"
37 static int match_callback(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
38 log_info("Match triggered! interface=%s member=%s", strna(sd_bus_message_get_interface(m)), strna(sd_bus_message_get_member(m)));
42 static int object_callback(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
47 if (sd_bus_message_is_method_error(m, NULL))
50 if (sd_bus_message_is_method_call(m, "org.object.test", "Foobar")) {
51 log_info("Invoked Foobar() on %s", sd_bus_message_get_path(m));
53 r = sd_bus_reply_method_return(m, NULL);
55 return log_error_errno(r, "Failed to send reply: %m");
63 static int server_init(sd_bus **_bus) {
71 r = sd_bus_open_user(&bus);
73 log_error_errno(r, "Failed to connect to user bus: %m");
77 r = sd_bus_get_bus_id(bus, &id);
79 log_error_errno(r, "Failed to get server ID: %m");
83 r = sd_bus_get_unique_name(bus, &unique);
85 log_error_errno(r, "Failed to get unique name: %m");
89 log_info("Peer ID is " SD_ID128_FORMAT_STR ".", SD_ID128_FORMAT_VAL(id));
90 log_info("Unique ID: %s", unique);
91 log_info("Can send file handles: %i", sd_bus_can_send(bus, 'h'));
93 r = sd_bus_request_name(bus, "org.freedesktop.systemd.test", 0);
95 log_error_errno(r, "Failed to acquire name: %m");
99 r = sd_bus_add_fallback(bus, NULL, "/foo/bar", object_callback, NULL);
101 log_error_errno(r, "Failed to add object: %m");
105 r = sd_bus_add_match(bus, NULL, "type='signal',interface='foo.bar',member='Notify'", match_callback, NULL);
107 log_error_errno(r, "Failed to add match: %m");
111 r = sd_bus_add_match(bus, NULL, "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged'", match_callback, NULL);
113 log_error_errno(r, "Failed to add match: %m");
117 bus_match_dump(&bus->match_callbacks, 0);
129 static int server(sd_bus *bus) {
131 bool client1_gone = false, client2_gone = false;
133 while (!client1_gone || !client2_gone) {
134 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
136 const char *label = NULL;
138 r = sd_bus_process(bus, &m);
140 log_error_errno(r, "Failed to process requests: %m");
145 r = sd_bus_wait(bus, (uint64_t) -1);
147 log_error_errno(r, "Failed to wait: %m");
157 sd_bus_creds_get_pid(sd_bus_message_get_creds(m), &pid);
158 sd_bus_creds_get_selinux_context(sd_bus_message_get_creds(m), &label);
159 log_info("Got message! member=%s pid="PID_FMT" label=%s",
160 strna(sd_bus_message_get_member(m)),
163 /* bus_message_dump(m); */
164 /* sd_bus_message_rewind(m, true); */
166 if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "LowerCase")) {
168 _cleanup_free_ char *lowercase = NULL;
170 r = sd_bus_message_read(m, "s", &hello);
172 log_error_errno(r, "Failed to get parameter: %m");
176 lowercase = strdup(hello);
182 ascii_strlower(lowercase);
184 r = sd_bus_reply_method_return(m, "s", lowercase);
186 log_error_errno(r, "Failed to send reply: %m");
189 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient1")) {
191 r = sd_bus_reply_method_return(m, NULL);
193 log_error_errno(r, "Failed to send reply: %m");
198 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient2")) {
200 r = sd_bus_reply_method_return(m, NULL);
202 log_error_errno(r, "Failed to send reply: %m");
207 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Slow")) {
211 r = sd_bus_reply_method_return(m, NULL);
213 log_error_errno(r, "Failed to send reply: %m");
217 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "FileDescriptor")) {
219 static const char x = 'X';
221 r = sd_bus_message_read(m, "h", &fd);
223 log_error_errno(r, "Failed to get parameter: %m");
227 log_info("Received fd=%d", fd);
229 if (write(fd, &x, 1) < 0) {
230 log_error_errno(errno, "Failed to write to fd: %m");
235 r = sd_bus_reply_method_return(m, NULL);
237 log_error_errno(r, "Failed to send reply: %m");
241 } else if (sd_bus_message_is_method_call(m, NULL, NULL)) {
243 r = sd_bus_reply_method_error(
245 &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method."));
247 log_error_errno(r, "Failed to send reply: %m");
264 static void* client1(void*p) {
265 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
267 sd_bus_error error = SD_BUS_ERROR_NULL;
270 int pp[2] = { -1, -1 };
273 r = sd_bus_open_user(&bus);
275 log_error_errno(r, "Failed to connect to user bus: %m");
279 r = sd_bus_call_method(
281 "org.freedesktop.systemd.test",
283 "org.freedesktop.systemd.test",
290 log_error_errno(r, "Failed to issue method call: %m");
294 r = sd_bus_message_read(reply, "s", &hello);
296 log_error_errno(r, "Failed to get string: %m");
300 assert_se(streq(hello, "hello"));
302 if (pipe2(pp, O_CLOEXEC|O_NONBLOCK) < 0) {
303 log_error_errno(errno, "Failed to allocate pipe: %m");
308 log_info("Sending fd=%d", pp[1]);
310 r = sd_bus_call_method(
312 "org.freedesktop.systemd.test",
314 "org.freedesktop.systemd.test",
321 log_error_errno(r, "Failed to issue method call: %m");
326 if (read(pp[0], &x, 1) <= 0) {
327 log_error("Failed to read from pipe: %s", errno ? strerror(errno) : "early read");
335 _cleanup_bus_message_unref_ sd_bus_message *q;
337 r = sd_bus_message_new_method_call(
340 "org.freedesktop.systemd.test",
342 "org.freedesktop.systemd.test",
345 log_error_errno(r, "Failed to allocate method call: %m");
347 sd_bus_send(bus, q, NULL);
353 sd_bus_error_free(&error);
357 return INT_TO_PTR(r);
360 static int quit_callback(sd_bus *b, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
363 log_error("Quit callback: %s", strerror(sd_bus_message_get_errno(m)));
369 static void* client2(void*p) {
370 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
372 sd_bus_error error = SD_BUS_ERROR_NULL;
377 r = sd_bus_open_user(&bus);
379 log_error_errno(r, "Failed to connect to user bus: %m");
383 r = sd_bus_message_new_method_call(
386 "org.freedesktop.systemd.test",
387 "/foo/bar/waldo/piep",
391 log_error_errno(r, "Failed to allocate method call: %m");
395 r = sd_bus_send(bus, m, NULL);
397 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
401 sd_bus_message_unref(m);
404 r = sd_bus_message_new_signal(
411 log_error_errno(r, "Failed to allocate signal: %m");
415 r = sd_bus_send(bus, m, NULL);
417 log_error("Failed to issue signal: %s", bus_error_message(&error, -r));
421 sd_bus_message_unref(m);
424 r = sd_bus_message_new_method_call(
427 "org.freedesktop.systemd.test",
429 "org.freedesktop.DBus.Peer",
432 log_error_errno(r, "Failed to allocate method call: %m");
436 r = sd_bus_call(bus, m, 0, &error, &reply);
438 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
442 r = sd_bus_message_read(reply, "s", &mid);
444 log_error_errno(r, "Failed to parse machine ID: %m");
448 log_info("Machine ID is %s.", mid);
450 sd_bus_message_unref(m);
453 r = sd_bus_message_new_method_call(
456 "org.freedesktop.systemd.test",
458 "org.freedesktop.systemd.test",
461 log_error_errno(r, "Failed to allocate method call: %m");
465 sd_bus_message_unref(reply);
468 r = sd_bus_call(bus, m, 200 * USEC_PER_MSEC, &error, &reply);
470 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
472 log_info("Slow call succeed.");
474 sd_bus_message_unref(m);
477 r = sd_bus_message_new_method_call(
480 "org.freedesktop.systemd.test",
482 "org.freedesktop.systemd.test",
485 log_error_errno(r, "Failed to allocate method call: %m");
489 r = sd_bus_call_async(bus, NULL, m, quit_callback, &quit, 200 * USEC_PER_MSEC);
491 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
496 r = sd_bus_process(bus, NULL);
498 log_error_errno(r, "Failed to process requests: %m");
502 r = sd_bus_wait(bus, (uint64_t) -1);
504 log_error_errno(r, "Failed to wait: %m");
514 _cleanup_bus_message_unref_ sd_bus_message *q;
516 r = sd_bus_message_new_method_call(
519 "org.freedesktop.systemd.test",
521 "org.freedesktop.systemd.test",
524 log_error_errno(r, "Failed to allocate method call: %m");
528 sd_bus_send(bus, q, NULL);
533 sd_bus_error_free(&error);
534 return INT_TO_PTR(r);
537 int main(int argc, char *argv[]) {
543 r = server_init(&bus);
545 log_info("Failed to connect to bus, skipping tests.");
546 return EXIT_TEST_SKIP;
549 log_info("Initialized...");
551 r = pthread_create(&c1, NULL, client1, bus);
555 r = pthread_create(&c2, NULL, client2, bus);
561 q = pthread_join(c1, &p);
564 if (PTR_TO_INT(p) < 0)
567 q = pthread_join(c2, &p);
570 if (PTR_TO_INT(p) < 0)