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"
37 static int match_callback(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_message
*m
, void *userdata
, sd_bus_error
*ret_error
) {
45 if (sd_bus_message_is_method_error(m
, NULL
))
48 if (sd_bus_message_is_method_call(m
, "org.object.test", "Foobar")) {
49 log_info("Invoked Foobar() on %s", sd_bus_message_get_path(m
));
51 r
= sd_bus_reply_method_return(m
, NULL
);
53 return log_error_errno(r
, "Failed to send reply: %m");
61 static int server_init(sd_bus
**_bus
) {
69 r
= sd_bus_open_user(&bus
);
71 log_error_errno(r
, "Failed to connect to user bus: %m");
75 r
= sd_bus_get_bus_id(bus
, &id
);
77 log_error_errno(r
, "Failed to get server ID: %m");
81 r
= sd_bus_get_unique_name(bus
, &unique
);
83 log_error_errno(r
, "Failed to get unique name: %m");
87 log_info("Peer ID is " SD_ID128_FORMAT_STR
".", SD_ID128_FORMAT_VAL(id
));
88 log_info("Unique ID: %s", unique
);
89 log_info("Can send file handles: %i", sd_bus_can_send(bus
, 'h'));
91 r
= sd_bus_request_name(bus
, "org.freedesktop.systemd.test", 0);
93 log_error_errno(r
, "Failed to acquire name: %m");
97 r
= sd_bus_add_fallback(bus
, NULL
, "/foo/bar", object_callback
, NULL
);
99 log_error_errno(r
, "Failed to add object: %m");
103 r
= sd_bus_add_match(bus
, NULL
, "type='signal',interface='foo.bar',member='Notify'", match_callback
, NULL
);
105 log_error_errno(r
, "Failed to add match: %m");
109 r
= sd_bus_add_match(bus
, NULL
, "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged'", match_callback
, NULL
);
111 log_error_errno(r
, "Failed to add match: %m");
115 bus_match_dump(&bus
->match_callbacks
, 0);
127 static int server(sd_bus
*bus
) {
129 bool client1_gone
= false, client2_gone
= false;
131 while (!client1_gone
|| !client2_gone
) {
132 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
134 const char *label
= NULL
;
136 r
= sd_bus_process(bus
, &m
);
138 log_error_errno(r
, "Failed to process requests: %m");
143 r
= sd_bus_wait(bus
, (uint64_t) -1);
145 log_error_errno(r
, "Failed to wait: %m");
155 sd_bus_creds_get_pid(sd_bus_message_get_creds(m
), &pid
);
156 sd_bus_creds_get_selinux_context(sd_bus_message_get_creds(m
), &label
);
157 log_info("Got message! member=%s pid="PID_FMT
" label=%s",
158 strna(sd_bus_message_get_member(m
)),
161 /* bus_message_dump(m); */
162 /* sd_bus_message_rewind(m, true); */
164 if (sd_bus_message_is_method_call(m
, "org.freedesktop.systemd.test", "LowerCase")) {
166 _cleanup_free_
char *lowercase
= NULL
;
168 r
= sd_bus_message_read(m
, "s", &hello
);
170 log_error_errno(r
, "Failed to get parameter: %m");
174 lowercase
= strdup(hello
);
180 ascii_strlower(lowercase
);
182 r
= sd_bus_reply_method_return(m
, "s", lowercase
);
184 log_error_errno(r
, "Failed to send reply: %m");
187 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.systemd.test", "ExitClient1")) {
189 r
= sd_bus_reply_method_return(m
, NULL
);
191 log_error_errno(r
, "Failed to send reply: %m");
196 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.systemd.test", "ExitClient2")) {
198 r
= sd_bus_reply_method_return(m
, NULL
);
200 log_error_errno(r
, "Failed to send reply: %m");
205 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.systemd.test", "Slow")) {
209 r
= sd_bus_reply_method_return(m
, NULL
);
211 log_error_errno(r
, "Failed to send reply: %m");
215 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.systemd.test", "FileDescriptor")) {
217 static const char x
= 'X';
219 r
= sd_bus_message_read(m
, "h", &fd
);
221 log_error_errno(r
, "Failed to get parameter: %m");
225 log_info("Received fd=%d", fd
);
227 if (write(fd
, &x
, 1) < 0) {
228 log_error_errno(errno
, "Failed to write to fd: %m");
233 r
= sd_bus_reply_method_return(m
, NULL
);
235 log_error_errno(r
, "Failed to send reply: %m");
239 } else if (sd_bus_message_is_method_call(m
, NULL
, NULL
)) {
241 r
= sd_bus_reply_method_error(
243 &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_UNKNOWN_METHOD
, "Unknown method."));
245 log_error_errno(r
, "Failed to send reply: %m");
262 static void* client1(void*p
) {
263 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
264 _cleanup_bus_flush_close_unref_ sd_bus
*bus
= NULL
;
265 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
268 _cleanup_close_pair_
int pp
[2] = { -1, -1 };
271 r
= sd_bus_open_user(&bus
);
273 log_error_errno(r
, "Failed to connect to user bus: %m");
277 r
= sd_bus_call_method(
279 "org.freedesktop.systemd.test",
281 "org.freedesktop.systemd.test",
288 log_error_errno(r
, "Failed to issue method call: %m");
292 r
= sd_bus_message_read(reply
, "s", &hello
);
294 log_error_errno(r
, "Failed to get string: %m");
298 assert_se(streq(hello
, "hello"));
300 if (pipe2(pp
, O_CLOEXEC
|O_NONBLOCK
) < 0) {
301 log_error_errno(errno
, "Failed to allocate pipe: %m");
306 log_info("Sending fd=%d", pp
[1]);
308 r
= sd_bus_call_method(
310 "org.freedesktop.systemd.test",
312 "org.freedesktop.systemd.test",
319 log_error_errno(r
, "Failed to issue method call: %m");
324 if (read(pp
[0], &x
, 1) <= 0) {
325 log_error("Failed to read from pipe: %s", errno
? strerror(errno
) : "early read");
333 _cleanup_bus_message_unref_ sd_bus_message
*q
;
335 r
= sd_bus_message_new_method_call(
338 "org.freedesktop.systemd.test",
340 "org.freedesktop.systemd.test",
343 log_error_errno(r
, "Failed to allocate method call: %m");
345 sd_bus_send(bus
, q
, NULL
);
349 return INT_TO_PTR(r
);
352 static int quit_callback(sd_bus_message
*m
, void *userdata
, sd_bus_error
*ret_error
) {
355 log_error("Quit callback: %s", strerror(sd_bus_message_get_errno(m
)));
361 static void* client2(void*p
) {
362 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
, *reply
= NULL
;
363 _cleanup_bus_flush_close_unref_ sd_bus
*bus
= NULL
;
364 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
369 r
= sd_bus_open_user(&bus
);
371 log_error_errno(r
, "Failed to connect to user bus: %m");
375 r
= sd_bus_message_new_method_call(
378 "org.freedesktop.systemd.test",
379 "/foo/bar/waldo/piep",
383 log_error_errno(r
, "Failed to allocate method call: %m");
387 r
= sd_bus_send(bus
, m
, NULL
);
389 log_error("Failed to issue method call: %s", bus_error_message(&error
, -r
));
393 m
= sd_bus_message_unref(m
);
395 r
= sd_bus_message_new_signal(
402 log_error_errno(r
, "Failed to allocate signal: %m");
406 r
= sd_bus_send(bus
, m
, NULL
);
408 log_error("Failed to issue signal: %s", bus_error_message(&error
, -r
));
412 m
= sd_bus_message_unref(m
);
414 r
= sd_bus_message_new_method_call(
417 "org.freedesktop.systemd.test",
419 "org.freedesktop.DBus.Peer",
422 log_error_errno(r
, "Failed to allocate method call: %m");
426 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
428 log_error("Failed to issue method call: %s", bus_error_message(&error
, -r
));
432 r
= sd_bus_message_read(reply
, "s", &mid
);
434 log_error_errno(r
, "Failed to parse machine ID: %m");
438 log_info("Machine ID is %s.", mid
);
440 m
= sd_bus_message_unref(m
);
442 r
= sd_bus_message_new_method_call(
445 "org.freedesktop.systemd.test",
447 "org.freedesktop.systemd.test",
450 log_error_errno(r
, "Failed to allocate method call: %m");
454 reply
= sd_bus_message_unref(reply
);
456 r
= sd_bus_call(bus
, m
, 200 * USEC_PER_MSEC
, &error
, &reply
);
458 log_info("Failed to issue method call: %s", bus_error_message(&error
, -r
));
460 log_info("Slow call succeed.");
462 m
= sd_bus_message_unref(m
);
464 r
= sd_bus_message_new_method_call(
467 "org.freedesktop.systemd.test",
469 "org.freedesktop.systemd.test",
472 log_error_errno(r
, "Failed to allocate method call: %m");
476 r
= sd_bus_call_async(bus
, NULL
, m
, quit_callback
, &quit
, 200 * USEC_PER_MSEC
);
478 log_info("Failed to issue method call: %s", bus_error_message(&error
, -r
));
483 r
= sd_bus_process(bus
, NULL
);
485 log_error_errno(r
, "Failed to process requests: %m");
489 r
= sd_bus_wait(bus
, (uint64_t) -1);
491 log_error_errno(r
, "Failed to wait: %m");
501 _cleanup_bus_message_unref_ sd_bus_message
*q
;
503 r
= sd_bus_message_new_method_call(
506 "org.freedesktop.systemd.test",
508 "org.freedesktop.systemd.test",
511 log_error_errno(r
, "Failed to allocate method call: %m");
515 (void) sd_bus_send(bus
, q
, NULL
);
518 return INT_TO_PTR(r
);
521 int main(int argc
, char *argv
[]) {
527 r
= server_init(&bus
);
529 log_info("Failed to connect to bus, skipping tests.");
530 return EXIT_TEST_SKIP
;
533 log_info("Initialized...");
535 r
= pthread_create(&c1
, NULL
, client1
, bus
);
539 r
= pthread_create(&c2
, NULL
, client2
, bus
);
545 q
= pthread_join(c1
, &p
);
548 if (PTR_TO_INT(p
) < 0)
551 q
= pthread_join(c2
, &p
);
554 if (PTR_TO_INT(p
) < 0)