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/>.
33 #include "bus-message.h"
34 #include "bus-error.h"
35 #include "bus-match.h"
36 #include "bus-internal.h"
39 static int match_callback(sd_bus
*bus
, sd_bus_message
*m
, void *userdata
, sd_bus_error
*ret_error
) {
40 log_info("Match triggered! interface=%s member=%s", strna(sd_bus_message_get_interface(m
)), strna(sd_bus_message_get_member(m
)));
44 static int object_callback(sd_bus
*bus
, sd_bus_message
*m
, void *userdata
, sd_bus_error
*ret_error
) {
49 if (sd_bus_message_is_method_error(m
, NULL
))
52 if (sd_bus_message_is_method_call(m
, "org.object.test", "Foobar")) {
53 log_info("Invoked Foobar() on %s", sd_bus_message_get_path(m
));
55 r
= sd_bus_reply_method_return(m
, NULL
);
57 return log_error_errno(r
, "Failed to send reply: %m");
65 static int server_init(sd_bus
**_bus
) {
73 r
= sd_bus_open_user(&bus
);
75 log_error_errno(r
, "Failed to connect to user bus: %m");
79 r
= sd_bus_get_owner_id(bus
, &id
);
81 log_error_errno(r
, "Failed to get server ID: %m");
85 r
= sd_bus_get_unique_name(bus
, &unique
);
87 log_error_errno(r
, "Failed to get unique name: %m");
91 log_info("Peer ID is " SD_ID128_FORMAT_STR
".", SD_ID128_FORMAT_VAL(id
));
92 log_info("Unique ID: %s", unique
);
93 log_info("Can send file handles: %i", sd_bus_can_send(bus
, 'h'));
95 r
= sd_bus_request_name(bus
, "org.freedesktop.systemd.test", 0);
97 log_error_errno(r
, "Failed to acquire name: %m");
101 r
= sd_bus_add_fallback(bus
, NULL
, "/foo/bar", object_callback
, NULL
);
103 log_error_errno(r
, "Failed to add object: %m");
107 r
= sd_bus_add_match(bus
, NULL
, "type='signal',interface='foo.bar',member='Notify'", match_callback
, NULL
);
109 log_error_errno(r
, "Failed to add match: %m");
113 r
= sd_bus_add_match(bus
, NULL
, "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged'", match_callback
, NULL
);
115 log_error_errno(r
, "Failed to add match: %m");
119 bus_match_dump(&bus
->match_callbacks
, 0);
131 static int server(sd_bus
*bus
) {
133 bool client1_gone
= false, client2_gone
= false;
135 while (!client1_gone
|| !client2_gone
) {
136 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
138 const char *label
= NULL
;
140 r
= sd_bus_process(bus
, &m
);
142 log_error_errno(r
, "Failed to process requests: %m");
147 r
= sd_bus_wait(bus
, (uint64_t) -1);
149 log_error_errno(r
, "Failed to wait: %m");
159 sd_bus_creds_get_pid(sd_bus_message_get_creds(m
), &pid
);
160 sd_bus_creds_get_selinux_context(sd_bus_message_get_creds(m
), &label
);
161 log_info("Got message! member=%s pid="PID_FMT
" label=%s",
162 strna(sd_bus_message_get_member(m
)),
165 /* bus_message_dump(m); */
166 /* sd_bus_message_rewind(m, true); */
168 if (sd_bus_message_is_method_call(m
, "org.freedesktop.systemd.test", "LowerCase")) {
170 _cleanup_free_
char *lowercase
= NULL
;
172 r
= sd_bus_message_read(m
, "s", &hello
);
174 log_error_errno(r
, "Failed to get parameter: %m");
178 lowercase
= strdup(hello
);
184 ascii_strlower(lowercase
);
186 r
= sd_bus_reply_method_return(m
, "s", lowercase
);
188 log_error_errno(r
, "Failed to send reply: %m");
191 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.systemd.test", "ExitClient1")) {
193 r
= sd_bus_reply_method_return(m
, NULL
);
195 log_error_errno(r
, "Failed to send reply: %m");
200 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.systemd.test", "ExitClient2")) {
202 r
= sd_bus_reply_method_return(m
, NULL
);
204 log_error_errno(r
, "Failed to send reply: %m");
209 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.systemd.test", "Slow")) {
213 r
= sd_bus_reply_method_return(m
, NULL
);
215 log_error_errno(r
, "Failed to send reply: %m");
219 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.systemd.test", "FileDescriptor")) {
221 static const char x
= 'X';
223 r
= sd_bus_message_read(m
, "h", &fd
);
225 log_error_errno(r
, "Failed to get parameter: %m");
229 log_info("Received fd=%d", fd
);
231 if (write(fd
, &x
, 1) < 0) {
232 log_error_errno(errno
, "Failed to write to fd: %m");
237 r
= sd_bus_reply_method_return(m
, NULL
);
239 log_error_errno(r
, "Failed to send reply: %m");
243 } else if (sd_bus_message_is_method_call(m
, NULL
, NULL
)) {
245 r
= sd_bus_reply_method_error(
247 &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_UNKNOWN_METHOD
, "Unknown method."));
249 log_error_errno(r
, "Failed to send reply: %m");
266 static void* client1(void*p
) {
267 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
269 sd_bus_error error
= SD_BUS_ERROR_NULL
;
272 int pp
[2] = { -1, -1 };
275 r
= sd_bus_open_user(&bus
);
277 log_error_errno(r
, "Failed to connect to user bus: %m");
281 r
= sd_bus_call_method(
283 "org.freedesktop.systemd.test",
285 "org.freedesktop.systemd.test",
292 log_error_errno(r
, "Failed to issue method call: %m");
296 r
= sd_bus_message_read(reply
, "s", &hello
);
298 log_error_errno(r
, "Failed to get string: %m");
302 assert(streq(hello
, "hello"));
304 if (pipe2(pp
, O_CLOEXEC
|O_NONBLOCK
) < 0) {
305 log_error_errno(errno
, "Failed to allocate pipe: %m");
310 log_info("Sending fd=%d", pp
[1]);
312 r
= sd_bus_call_method(
314 "org.freedesktop.systemd.test",
316 "org.freedesktop.systemd.test",
323 log_error_errno(r
, "Failed to issue method call: %m");
328 if (read(pp
[0], &x
, 1) <= 0) {
329 log_error("Failed to read from pipe: %s", errno
? strerror(errno
) : "early read");
337 _cleanup_bus_message_unref_ sd_bus_message
*q
;
339 r
= sd_bus_message_new_method_call(
342 "org.freedesktop.systemd.test",
344 "org.freedesktop.systemd.test",
347 log_error_errno(r
, "Failed to allocate method call: %m");
349 sd_bus_send(bus
, q
, NULL
);
355 sd_bus_error_free(&error
);
359 return INT_TO_PTR(r
);
362 static int quit_callback(sd_bus
*b
, sd_bus_message
*m
, void *userdata
, sd_bus_error
*ret_error
) {
365 log_error("Quit callback: %s", strerror(sd_bus_message_get_errno(m
)));
371 static void* client2(void*p
) {
372 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
, *reply
= NULL
;
374 sd_bus_error error
= SD_BUS_ERROR_NULL
;
379 r
= sd_bus_open_user(&bus
);
381 log_error_errno(r
, "Failed to connect to user bus: %m");
385 r
= sd_bus_message_new_method_call(
388 "org.freedesktop.systemd.test",
389 "/foo/bar/waldo/piep",
393 log_error_errno(r
, "Failed to allocate method call: %m");
397 r
= sd_bus_send(bus
, m
, NULL
);
399 log_error("Failed to issue method call: %s", bus_error_message(&error
, -r
));
403 sd_bus_message_unref(m
);
406 r
= sd_bus_message_new_signal(
413 log_error_errno(r
, "Failed to allocate signal: %m");
417 r
= sd_bus_send(bus
, m
, NULL
);
419 log_error("Failed to issue signal: %s", bus_error_message(&error
, -r
));
423 sd_bus_message_unref(m
);
426 r
= sd_bus_message_new_method_call(
429 "org.freedesktop.systemd.test",
431 "org.freedesktop.DBus.Peer",
434 log_error_errno(r
, "Failed to allocate method call: %m");
438 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
440 log_error("Failed to issue method call: %s", bus_error_message(&error
, -r
));
444 r
= sd_bus_message_read(reply
, "s", &mid
);
446 log_error_errno(r
, "Failed to parse machine ID: %m");
450 log_info("Machine ID is %s.", mid
);
452 sd_bus_message_unref(m
);
455 r
= sd_bus_message_new_method_call(
458 "org.freedesktop.systemd.test",
460 "org.freedesktop.systemd.test",
463 log_error_errno(r
, "Failed to allocate method call: %m");
467 sd_bus_message_unref(reply
);
470 r
= sd_bus_call(bus
, m
, 200 * USEC_PER_MSEC
, &error
, &reply
);
472 log_info("Failed to issue method call: %s", bus_error_message(&error
, -r
));
474 log_info("Slow call succeed.");
476 sd_bus_message_unref(m
);
479 r
= sd_bus_message_new_method_call(
482 "org.freedesktop.systemd.test",
484 "org.freedesktop.systemd.test",
487 log_error_errno(r
, "Failed to allocate method call: %m");
491 r
= sd_bus_call_async(bus
, NULL
, m
, quit_callback
, &quit
, 200 * USEC_PER_MSEC
);
493 log_info("Failed to issue method call: %s", bus_error_message(&error
, -r
));
498 r
= sd_bus_process(bus
, NULL
);
500 log_error_errno(r
, "Failed to process requests: %m");
504 r
= sd_bus_wait(bus
, (uint64_t) -1);
506 log_error_errno(r
, "Failed to wait: %m");
516 _cleanup_bus_message_unref_ sd_bus_message
*q
;
518 r
= sd_bus_message_new_method_call(
521 "org.freedesktop.systemd.test",
523 "org.freedesktop.systemd.test",
526 log_error_errno(r
, "Failed to allocate method call: %m");
530 sd_bus_send(bus
, q
, NULL
);
535 sd_bus_error_free(&error
);
536 return INT_TO_PTR(r
);
539 int main(int argc
, char *argv
[]) {
545 r
= server_init(&bus
);
547 log_info("Failed to connect to bus, skipping tests.");
548 return EXIT_TEST_SKIP
;
551 log_info("Initialized...");
553 r
= pthread_create(&c1
, NULL
, client1
, bus
);
557 r
= pthread_create(&c2
, NULL
, client2
, bus
);
563 q
= pthread_join(c1
, &p
);
566 if (PTR_TO_INT(p
) < 0)
569 q
= pthread_join(c2
, &p
);
572 if (PTR_TO_INT(p
) < 0)