1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright 2013 Lennart Poettering
13 #include "alloc-util.h"
14 #include "bus-error.h"
15 #include "bus-internal.h"
16 #include "bus-match.h"
19 #include "format-util.h"
24 static int match_callback(sd_bus_message
*m
, void *userdata
, sd_bus_error
*ret_error
) {
25 log_info("Match triggered! interface=%s member=%s", strna(sd_bus_message_get_interface(m
)), strna(sd_bus_message_get_member(m
)));
29 static int object_callback(sd_bus_message
*m
, void *userdata
, sd_bus_error
*ret_error
) {
32 if (sd_bus_message_is_method_error(m
, NULL
))
35 if (sd_bus_message_is_method_call(m
, "org.object.test", "Foobar")) {
36 log_info("Invoked Foobar() on %s", sd_bus_message_get_path(m
));
38 r
= sd_bus_reply_method_return(m
, NULL
);
40 return log_error_errno(r
, "Failed to send reply: %m");
48 static int server_init(sd_bus
**_bus
) {
52 const char *unique
, *desc
;
56 r
= sd_bus_open_user_with_description(&bus
, "my bus!");
58 log_error_errno(r
, "Failed to connect to user bus: %m");
62 r
= sd_bus_get_bus_id(bus
, &id
);
64 log_error_errno(r
, "Failed to get server ID: %m");
68 r
= sd_bus_get_unique_name(bus
, &unique
);
70 log_error_errno(r
, "Failed to get unique name: %m");
74 r
= sd_bus_get_description(bus
, &desc
);
75 assert_se(streq(desc
, "my bus!"));
77 log_info("Peer ID is " SD_ID128_FORMAT_STR
".", SD_ID128_FORMAT_VAL(id
));
78 log_info("Unique ID: %s", unique
);
79 log_info("Can send file handles: %i", sd_bus_can_send(bus
, 'h'));
81 r
= sd_bus_request_name(bus
, "org.freedesktop.systemd.test", 0);
83 log_error_errno(r
, "Failed to acquire name: %m");
87 r
= sd_bus_add_fallback(bus
, NULL
, "/foo/bar", object_callback
, NULL
);
89 log_error_errno(r
, "Failed to add object: %m");
93 r
= sd_bus_match_signal(bus
, NULL
, NULL
, NULL
, "foo.bar", "Notify", match_callback
, NULL
);
95 log_error_errno(r
, "Failed to request match: %m");
99 r
= sd_bus_add_match(bus
, NULL
, "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged'", match_callback
, NULL
);
101 log_error_errno(r
, "Failed to add match: %m");
105 bus_match_dump(&bus
->match_callbacks
, 0);
115 static int server(sd_bus
*bus
) {
117 bool client1_gone
= false, client2_gone
= false;
119 while (!client1_gone
|| !client2_gone
) {
120 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
122 const char *label
= NULL
;
124 r
= sd_bus_process(bus
, &m
);
126 log_error_errno(r
, "Failed to process requests: %m");
131 r
= sd_bus_wait(bus
, (uint64_t) -1);
133 log_error_errno(r
, "Failed to wait: %m");
143 sd_bus_creds_get_pid(sd_bus_message_get_creds(m
), &pid
);
144 sd_bus_creds_get_selinux_context(sd_bus_message_get_creds(m
), &label
);
145 log_info("Got message! member=%s pid="PID_FMT
" label=%s",
146 strna(sd_bus_message_get_member(m
)),
149 /* bus_message_dump(m); */
150 /* sd_bus_message_rewind(m, true); */
152 if (sd_bus_message_is_method_call(m
, "org.freedesktop.systemd.test", "LowerCase")) {
154 _cleanup_free_
char *lowercase
= NULL
;
156 r
= sd_bus_message_read(m
, "s", &hello
);
158 log_error_errno(r
, "Failed to get parameter: %m");
162 lowercase
= strdup(hello
);
168 ascii_strlower(lowercase
);
170 r
= sd_bus_reply_method_return(m
, "s", lowercase
);
172 log_error_errno(r
, "Failed to send reply: %m");
175 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.systemd.test", "ExitClient1")) {
177 r
= sd_bus_reply_method_return(m
, NULL
);
179 log_error_errno(r
, "Failed to send reply: %m");
184 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.systemd.test", "ExitClient2")) {
186 r
= sd_bus_reply_method_return(m
, NULL
);
188 log_error_errno(r
, "Failed to send reply: %m");
193 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.systemd.test", "Slow")) {
197 r
= sd_bus_reply_method_return(m
, NULL
);
199 log_error_errno(r
, "Failed to send reply: %m");
203 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.systemd.test", "FileDescriptor")) {
205 static const char x
= 'X';
207 r
= sd_bus_message_read(m
, "h", &fd
);
209 log_error_errno(r
, "Failed to get parameter: %m");
213 log_info("Received fd=%d", fd
);
215 if (write(fd
, &x
, 1) < 0) {
216 log_error_errno(errno
, "Failed to write to fd: %m");
221 r
= sd_bus_reply_method_return(m
, NULL
);
223 log_error_errno(r
, "Failed to send reply: %m");
227 } else if (sd_bus_message_is_method_call(m
, NULL
, NULL
)) {
229 r
= sd_bus_reply_method_error(
231 &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_UNKNOWN_METHOD
, "Unknown method."));
233 log_error_errno(r
, "Failed to send reply: %m");
250 static void* client1(void*p
) {
251 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
252 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
253 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
256 _cleanup_close_pair_
int pp
[2] = { -1, -1 };
259 r
= sd_bus_open_user(&bus
);
261 log_error_errno(r
, "Failed to connect to user bus: %m");
265 r
= sd_bus_call_method(
267 "org.freedesktop.systemd.test",
269 "org.freedesktop.systemd.test",
276 log_error_errno(r
, "Failed to issue method call: %m");
280 r
= sd_bus_message_read(reply
, "s", &hello
);
282 log_error_errno(r
, "Failed to get string: %m");
286 assert_se(streq(hello
, "hello"));
288 if (pipe2(pp
, O_CLOEXEC
|O_NONBLOCK
) < 0) {
289 log_error_errno(errno
, "Failed to allocate pipe: %m");
294 log_info("Sending fd=%d", pp
[1]);
296 r
= sd_bus_call_method(
298 "org.freedesktop.systemd.test",
300 "org.freedesktop.systemd.test",
307 log_error_errno(r
, "Failed to issue method call: %m");
312 if (read(pp
[0], &x
, 1) <= 0) {
313 log_error("Failed to read from pipe: %s", errno
? strerror(errno
) : "early read");
321 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*q
;
323 r
= sd_bus_message_new_method_call(
326 "org.freedesktop.systemd.test",
328 "org.freedesktop.systemd.test",
331 log_error_errno(r
, "Failed to allocate method call: %m");
333 sd_bus_send(bus
, q
, NULL
);
337 return INT_TO_PTR(r
);
340 static int quit_callback(sd_bus_message
*m
, void *userdata
, sd_bus_error
*ret_error
) {
343 log_error_errno(sd_bus_message_get_errno(m
), "Quit callback: %m");
349 static void* client2(void*p
) {
350 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
, *reply
= NULL
;
351 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
352 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
357 r
= sd_bus_open_user(&bus
);
359 log_error_errno(r
, "Failed to connect to user bus: %m");
363 r
= sd_bus_message_new_method_call(
366 "org.freedesktop.systemd.test",
367 "/foo/bar/waldo/piep",
371 log_error_errno(r
, "Failed to allocate method call: %m");
375 r
= sd_bus_send(bus
, m
, NULL
);
377 log_error("Failed to issue method call: %s", bus_error_message(&error
, -r
));
381 m
= sd_bus_message_unref(m
);
383 r
= sd_bus_message_new_signal(
390 log_error_errno(r
, "Failed to allocate signal: %m");
394 r
= sd_bus_send(bus
, m
, NULL
);
396 log_error("Failed to issue signal: %s", bus_error_message(&error
, -r
));
400 m
= sd_bus_message_unref(m
);
402 r
= sd_bus_message_new_method_call(
405 "org.freedesktop.systemd.test",
407 "org.freedesktop.DBus.Peer",
410 log_error_errno(r
, "Failed to allocate method call: %m");
414 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
416 log_error("Failed to issue method call: %s", bus_error_message(&error
, -r
));
420 r
= sd_bus_message_read(reply
, "s", &mid
);
422 log_error_errno(r
, "Failed to parse machine ID: %m");
426 log_info("Machine ID is %s.", mid
);
428 m
= sd_bus_message_unref(m
);
430 r
= sd_bus_message_new_method_call(
433 "org.freedesktop.systemd.test",
435 "org.freedesktop.systemd.test",
438 log_error_errno(r
, "Failed to allocate method call: %m");
442 reply
= sd_bus_message_unref(reply
);
444 r
= sd_bus_call(bus
, m
, 200 * USEC_PER_MSEC
, &error
, &reply
);
446 log_info("Failed to issue method call: %s", bus_error_message(&error
, -r
));
448 log_info("Slow call succeed.");
450 m
= sd_bus_message_unref(m
);
452 r
= sd_bus_message_new_method_call(
455 "org.freedesktop.systemd.test",
457 "org.freedesktop.systemd.test",
460 log_error_errno(r
, "Failed to allocate method call: %m");
464 r
= sd_bus_call_async(bus
, NULL
, m
, quit_callback
, &quit
, 200 * USEC_PER_MSEC
);
466 log_info("Failed to issue method call: %s", bus_error_message(&error
, -r
));
471 r
= sd_bus_process(bus
, NULL
);
473 log_error_errno(r
, "Failed to process requests: %m");
477 r
= sd_bus_wait(bus
, (uint64_t) -1);
479 log_error_errno(r
, "Failed to wait: %m");
489 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*q
;
491 r
= sd_bus_message_new_method_call(
494 "org.freedesktop.systemd.test",
496 "org.freedesktop.systemd.test",
499 log_error_errno(r
, "Failed to allocate method call: %m");
503 (void) sd_bus_send(bus
, q
, NULL
);
506 return INT_TO_PTR(r
);
509 int main(int argc
, char *argv
[]) {
515 r
= server_init(&bus
);
517 log_info("Failed to connect to bus, skipping tests.");
518 return EXIT_TEST_SKIP
;
521 log_info("Initialized...");
523 r
= pthread_create(&c1
, NULL
, client1
, bus
);
527 r
= pthread_create(&c2
, NULL
, client2
, bus
);
533 q
= pthread_join(c1
, &p
);
536 if (PTR_TO_INT(p
) < 0)
539 q
= pthread_join(c2
, &p
);
542 if (PTR_TO_INT(p
) < 0)