2 This file is part of systemd.
4 Copyright 2013 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
27 #include "alloc-util.h"
28 #include "bus-error.h"
29 #include "bus-internal.h"
30 #include "bus-match.h"
33 #include "format-util.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);
126 static int server(sd_bus
*bus
) {
128 bool client1_gone
= false, client2_gone
= false;
130 while (!client1_gone
|| !client2_gone
) {
131 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
133 const char *label
= NULL
;
135 r
= sd_bus_process(bus
, &m
);
137 log_error_errno(r
, "Failed to process requests: %m");
142 r
= sd_bus_wait(bus
, (uint64_t) -1);
144 log_error_errno(r
, "Failed to wait: %m");
154 sd_bus_creds_get_pid(sd_bus_message_get_creds(m
), &pid
);
155 sd_bus_creds_get_selinux_context(sd_bus_message_get_creds(m
), &label
);
156 log_info("Got message! member=%s pid="PID_FMT
" label=%s",
157 strna(sd_bus_message_get_member(m
)),
160 /* bus_message_dump(m); */
161 /* sd_bus_message_rewind(m, true); */
163 if (sd_bus_message_is_method_call(m
, "org.freedesktop.systemd.test", "LowerCase")) {
165 _cleanup_free_
char *lowercase
= NULL
;
167 r
= sd_bus_message_read(m
, "s", &hello
);
169 log_error_errno(r
, "Failed to get parameter: %m");
173 lowercase
= strdup(hello
);
179 ascii_strlower(lowercase
);
181 r
= sd_bus_reply_method_return(m
, "s", lowercase
);
183 log_error_errno(r
, "Failed to send reply: %m");
186 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.systemd.test", "ExitClient1")) {
188 r
= sd_bus_reply_method_return(m
, NULL
);
190 log_error_errno(r
, "Failed to send reply: %m");
195 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.systemd.test", "ExitClient2")) {
197 r
= sd_bus_reply_method_return(m
, NULL
);
199 log_error_errno(r
, "Failed to send reply: %m");
204 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.systemd.test", "Slow")) {
208 r
= sd_bus_reply_method_return(m
, NULL
);
210 log_error_errno(r
, "Failed to send reply: %m");
214 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.systemd.test", "FileDescriptor")) {
216 static const char x
= 'X';
218 r
= sd_bus_message_read(m
, "h", &fd
);
220 log_error_errno(r
, "Failed to get parameter: %m");
224 log_info("Received fd=%d", fd
);
226 if (write(fd
, &x
, 1) < 0) {
227 log_error_errno(errno
, "Failed to write to fd: %m");
232 r
= sd_bus_reply_method_return(m
, NULL
);
234 log_error_errno(r
, "Failed to send reply: %m");
238 } else if (sd_bus_message_is_method_call(m
, NULL
, NULL
)) {
240 r
= sd_bus_reply_method_error(
242 &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_UNKNOWN_METHOD
, "Unknown method."));
244 log_error_errno(r
, "Failed to send reply: %m");
261 static void* client1(void*p
) {
262 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
263 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
264 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
267 _cleanup_close_pair_
int pp
[2] = { -1, -1 };
270 r
= sd_bus_open_user(&bus
);
272 log_error_errno(r
, "Failed to connect to user bus: %m");
276 r
= sd_bus_call_method(
278 "org.freedesktop.systemd.test",
280 "org.freedesktop.systemd.test",
287 log_error_errno(r
, "Failed to issue method call: %m");
291 r
= sd_bus_message_read(reply
, "s", &hello
);
293 log_error_errno(r
, "Failed to get string: %m");
297 assert_se(streq(hello
, "hello"));
299 if (pipe2(pp
, O_CLOEXEC
|O_NONBLOCK
) < 0) {
300 log_error_errno(errno
, "Failed to allocate pipe: %m");
305 log_info("Sending fd=%d", pp
[1]);
307 r
= sd_bus_call_method(
309 "org.freedesktop.systemd.test",
311 "org.freedesktop.systemd.test",
318 log_error_errno(r
, "Failed to issue method call: %m");
323 if (read(pp
[0], &x
, 1) <= 0) {
324 log_error("Failed to read from pipe: %s", errno
? strerror(errno
) : "early read");
332 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*q
;
334 r
= sd_bus_message_new_method_call(
337 "org.freedesktop.systemd.test",
339 "org.freedesktop.systemd.test",
342 log_error_errno(r
, "Failed to allocate method call: %m");
344 sd_bus_send(bus
, q
, NULL
);
348 return INT_TO_PTR(r
);
351 static int quit_callback(sd_bus_message
*m
, void *userdata
, sd_bus_error
*ret_error
) {
354 log_error_errno(sd_bus_message_get_errno(m
), "Quit callback: %m");
360 static void* client2(void*p
) {
361 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
, *reply
= NULL
;
362 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
363 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
368 r
= sd_bus_open_user(&bus
);
370 log_error_errno(r
, "Failed to connect to user bus: %m");
374 r
= sd_bus_message_new_method_call(
377 "org.freedesktop.systemd.test",
378 "/foo/bar/waldo/piep",
382 log_error_errno(r
, "Failed to allocate method call: %m");
386 r
= sd_bus_send(bus
, m
, NULL
);
388 log_error("Failed to issue method call: %s", bus_error_message(&error
, -r
));
392 m
= sd_bus_message_unref(m
);
394 r
= sd_bus_message_new_signal(
401 log_error_errno(r
, "Failed to allocate signal: %m");
405 r
= sd_bus_send(bus
, m
, NULL
);
407 log_error("Failed to issue signal: %s", bus_error_message(&error
, -r
));
411 m
= sd_bus_message_unref(m
);
413 r
= sd_bus_message_new_method_call(
416 "org.freedesktop.systemd.test",
418 "org.freedesktop.DBus.Peer",
421 log_error_errno(r
, "Failed to allocate method call: %m");
425 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
427 log_error("Failed to issue method call: %s", bus_error_message(&error
, -r
));
431 r
= sd_bus_message_read(reply
, "s", &mid
);
433 log_error_errno(r
, "Failed to parse machine ID: %m");
437 log_info("Machine ID is %s.", mid
);
439 m
= sd_bus_message_unref(m
);
441 r
= sd_bus_message_new_method_call(
444 "org.freedesktop.systemd.test",
446 "org.freedesktop.systemd.test",
449 log_error_errno(r
, "Failed to allocate method call: %m");
453 reply
= sd_bus_message_unref(reply
);
455 r
= sd_bus_call(bus
, m
, 200 * USEC_PER_MSEC
, &error
, &reply
);
457 log_info("Failed to issue method call: %s", bus_error_message(&error
, -r
));
459 log_info("Slow call succeed.");
461 m
= sd_bus_message_unref(m
);
463 r
= sd_bus_message_new_method_call(
466 "org.freedesktop.systemd.test",
468 "org.freedesktop.systemd.test",
471 log_error_errno(r
, "Failed to allocate method call: %m");
475 r
= sd_bus_call_async(bus
, NULL
, m
, quit_callback
, &quit
, 200 * USEC_PER_MSEC
);
477 log_info("Failed to issue method call: %s", bus_error_message(&error
, -r
));
482 r
= sd_bus_process(bus
, NULL
);
484 log_error_errno(r
, "Failed to process requests: %m");
488 r
= sd_bus_wait(bus
, (uint64_t) -1);
490 log_error_errno(r
, "Failed to wait: %m");
500 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*q
;
502 r
= sd_bus_message_new_method_call(
505 "org.freedesktop.systemd.test",
507 "org.freedesktop.systemd.test",
510 log_error_errno(r
, "Failed to allocate method call: %m");
514 (void) sd_bus_send(bus
, q
, NULL
);
517 return INT_TO_PTR(r
);
520 int main(int argc
, char *argv
[]) {
526 r
= server_init(&bus
);
528 log_info("Failed to connect to bus, skipping tests.");
529 return EXIT_TEST_SKIP
;
532 log_info("Initialized...");
534 r
= pthread_create(&c1
, NULL
, client1
, bus
);
538 r
= pthread_create(&c2
, NULL
, client2
, bus
);
544 q
= pthread_join(c1
, &p
);
547 if (PTR_TO_INT(p
) < 0)
550 q
= pthread_join(c2
, &p
);
553 if (PTR_TO_INT(p
) < 0)