1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
9 #include "alloc-util.h"
10 #include "bus-error.h"
11 #include "bus-internal.h"
12 #include "bus-match.h"
13 #include "errno-util.h"
15 #include "format-util.h"
17 #include "string-util.h"
19 #include "time-util.h"
21 static int match_callback(sd_bus_message
*m
, void *userdata
, sd_bus_error
*ret_error
) {
22 log_info("Match triggered! destination=%s interface=%s member=%s",
23 strna(sd_bus_message_get_destination(m
)),
24 strna(sd_bus_message_get_interface(m
)),
25 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
**ret_bus
) {
49 _cleanup_(sd_bus_unrefp
) sd_bus
*bus
= NULL
;
50 const char *unique
, *desc
;
56 r
= sd_bus_open_user_with_description(&bus
, "my bus!");
58 return log_error_errno(r
, "Failed to connect to user bus: %m");
60 r
= sd_bus_get_bus_id(bus
, &id
);
62 return log_error_errno(r
, "Failed to get server ID: %m");
64 r
= sd_bus_get_unique_name(bus
, &unique
);
66 return log_error_errno(r
, "Failed to get unique name: %m");
68 assert_se(sd_bus_get_description(bus
, &desc
) >= 0);
69 assert_se(streq(desc
, "my bus!"));
71 log_info("Peer ID is " SD_ID128_FORMAT_STR
".", SD_ID128_FORMAT_VAL(id
));
72 log_info("Unique ID: %s", unique
);
73 log_info("Can send file handles: %i", sd_bus_can_send(bus
, 'h'));
75 r
= sd_bus_request_name(bus
, "org.freedesktop.systemd.test", 0);
77 return log_error_errno(r
, "Failed to acquire name: %m");
79 r
= sd_bus_add_fallback(bus
, NULL
, "/foo/bar", object_callback
, NULL
);
81 return log_error_errno(r
, "Failed to add object: %m");
83 r
= sd_bus_match_signal(bus
, NULL
, NULL
, NULL
, "foo.bar", "Notify", match_callback
, NULL
);
85 return log_error_errno(r
, "Failed to request match: %m");
87 r
= sd_bus_match_signal(bus
, NULL
, NULL
, NULL
, "foo.bar", "NotifyTo", match_callback
, NULL
);
89 return log_error_errno(r
, "Failed to request match: %m");
91 r
= sd_bus_add_match(bus
, NULL
, "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged'", match_callback
, NULL
);
93 return log_error_errno(r
, "Failed to add match: %m");
95 bus_match_dump(stdout
, &bus
->match_callbacks
, 0);
97 *ret_bus
= TAKE_PTR(bus
);
101 static int server(sd_bus
*_bus
) {
102 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= ASSERT_PTR(_bus
);
103 bool client1_gone
= false, client2_gone
= false;
106 while (!client1_gone
|| !client2_gone
) {
107 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
108 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
110 const char *label
= NULL
;
112 r
= sd_bus_process(bus
, &m
);
114 return log_error_errno(r
, "Failed to process requests: %m");
116 r
= sd_bus_wait(bus
, UINT64_MAX
);
118 return log_error_errno(r
, "Failed to wait: %m");
125 r
= sd_bus_query_sender_creds(m
, SD_BUS_CREDS_AUGMENT
| SD_BUS_CREDS_PID
| SD_BUS_CREDS_SELINUX_CONTEXT
, &creds
);
127 log_debug_errno(r
, "Failed to query sender credentials, ignoring: %m");
129 r
= sd_bus_creds_get_pid(creds
, &pid
);
131 return log_error_errno(r
, "Failed to get sender pid: %m");
133 (void) sd_bus_creds_get_selinux_context(creds
, &label
);
136 log_info("Got message! member=%s pid="PID_FMT
" label=%s",
137 strna(sd_bus_message_get_member(m
)),
141 /* sd_bus_message_dump(m); */
142 /* sd_bus_message_rewind(m, true); */
144 if (sd_bus_message_is_method_call(m
, "org.freedesktop.systemd.test", "LowerCase")) {
146 _cleanup_free_
char *lowercase
= NULL
;
148 r
= sd_bus_message_read(m
, "s", &hello
);
150 return log_error_errno(r
, "Failed to get parameter: %m");
152 lowercase
= strdup(hello
);
156 ascii_strlower(lowercase
);
158 r
= sd_bus_reply_method_return(m
, "s", lowercase
);
160 return log_error_errno(r
, "Failed to send reply: %m");
162 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.systemd.test", "ExitClient1")) {
164 r
= sd_bus_reply_method_return(m
, NULL
);
166 return log_error_errno(r
, "Failed to send reply: %m");
169 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.systemd.test", "ExitClient2")) {
171 r
= sd_bus_reply_method_return(m
, NULL
);
173 return log_error_errno(r
, "Failed to send reply: %m");
176 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.systemd.test", "Slow")) {
180 r
= sd_bus_reply_method_return(m
, NULL
);
182 return log_error_errno(r
, "Failed to send reply: %m");
184 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.systemd.test", "FileDescriptor")) {
186 static const char x
= 'X';
188 r
= sd_bus_message_read(m
, "h", &fd
);
190 return log_error_errno(r
, "Failed to get parameter: %m");
192 log_info("Received fd=%d", fd
);
194 if (write(fd
, &x
, 1) < 0) {
195 r
= log_error_errno(errno
, "Failed to write to fd: %m");
200 r
= sd_bus_reply_method_return(m
, NULL
);
202 return log_error_errno(r
, "Failed to send reply: %m");
204 } else if (sd_bus_message_is_method_call(m
, NULL
, NULL
)) {
206 r
= sd_bus_reply_method_error(
208 &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_UNKNOWN_METHOD
, "Unknown method."));
210 return log_error_errno(r
, "Failed to send reply: %m");
217 static void* client1(void *p
) {
218 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
219 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
220 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
223 _cleanup_close_pair_
int pp
[2] = EBADF_PAIR
;
226 r
= sd_bus_open_user(&bus
);
228 log_error_errno(r
, "Failed to connect to user bus: %m");
232 r
= sd_bus_call_method(
234 "org.freedesktop.systemd.test",
236 "org.freedesktop.systemd.test",
243 log_error_errno(r
, "Failed to issue method call: %m");
247 r
= sd_bus_message_read(reply
, "s", &hello
);
249 log_error_errno(r
, "Failed to get string: %m");
253 assert_se(streq(hello
, "hello"));
255 if (pipe2(pp
, O_CLOEXEC
|O_NONBLOCK
) < 0) {
256 r
= log_error_errno(errno
, "Failed to allocate pipe: %m");
260 log_info("Sending fd=%d", pp
[1]);
262 r
= sd_bus_call_method(
264 "org.freedesktop.systemd.test",
266 "org.freedesktop.systemd.test",
273 log_error_errno(r
, "Failed to issue method call: %m");
278 if (read(pp
[0], &x
, 1) <= 0) {
279 log_error("Failed to read from pipe: %s", STRERROR_OR_EOF(errno
));
287 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*q
= NULL
;
289 r
= sd_bus_message_new_method_call(
292 "org.freedesktop.systemd.test",
294 "org.freedesktop.systemd.test",
297 log_error_errno(r
, "Failed to allocate method call: %m");
299 sd_bus_send(bus
, q
, NULL
);
303 return INT_TO_PTR(r
);
306 static int quit_callback(sd_bus_message
*m
, void *userdata
, sd_bus_error
*ret_error
) {
309 log_error_errno(sd_bus_message_get_errno(m
), "Quit callback: %m");
315 static void* client2(void *p
) {
316 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
, *reply
= NULL
;
317 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
318 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
323 r
= sd_bus_open_user(&bus
);
325 log_error_errno(r
, "Failed to connect to user bus: %m");
329 r
= sd_bus_message_new_method_call(
332 "org.freedesktop.systemd.test",
333 "/foo/bar/waldo/piep",
337 log_error_errno(r
, "Failed to allocate method call: %m");
341 r
= sd_bus_send(bus
, m
, NULL
);
343 log_error("Failed to issue method call: %s", bus_error_message(&error
, r
));
347 m
= sd_bus_message_unref(m
);
349 r
= sd_bus_message_new_signal(
356 log_error_errno(r
, "Failed to allocate signal: %m");
360 r
= sd_bus_send(bus
, m
, NULL
);
362 log_error("Failed to issue signal: %s", bus_error_message(&error
, r
));
366 m
= sd_bus_message_unref(m
);
368 r
= sd_bus_message_new_signal_to(
371 "org.freedesktop.systemd.test",
376 log_error_errno(r
, "Failed to allocate signal to: %m");
380 r
= sd_bus_send(bus
, m
, NULL
);
382 log_error("Failed to issue signal to: %s", bus_error_message(&error
, r
));
386 m
= sd_bus_message_unref(m
);
388 r
= sd_bus_message_new_method_call(
391 "org.freedesktop.systemd.test",
393 "org.freedesktop.DBus.Peer",
396 log_error_errno(r
, "Failed to allocate method call: %m");
400 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
402 log_error("Failed to issue method call: %s", bus_error_message(&error
, r
));
406 r
= sd_bus_message_read(reply
, "s", &mid
);
408 log_error_errno(r
, "Failed to parse machine ID: %m");
412 log_info("Machine ID is %s.", mid
);
414 m
= sd_bus_message_unref(m
);
416 r
= sd_bus_message_new_method_call(
419 "org.freedesktop.systemd.test",
421 "org.freedesktop.systemd.test",
424 log_error_errno(r
, "Failed to allocate method call: %m");
428 reply
= sd_bus_message_unref(reply
);
430 r
= sd_bus_call(bus
, m
, 200 * USEC_PER_MSEC
, &error
, &reply
);
432 log_debug("Failed to issue method call: %s", bus_error_message(&error
, r
));
434 r
= log_error_errno(SYNTHETIC_ERRNO(ENOANO
), "Slow call unexpectedly succeeded.");
438 m
= sd_bus_message_unref(m
);
440 r
= sd_bus_message_new_method_call(
443 "org.freedesktop.systemd.test",
445 "org.freedesktop.systemd.test",
448 log_error_errno(r
, "Failed to allocate method call: %m");
452 r
= sd_bus_call_async(bus
, NULL
, m
, quit_callback
, &quit
, 200 * USEC_PER_MSEC
);
454 log_info("Failed to issue method call: %s", bus_error_message(&error
, r
));
459 r
= sd_bus_process(bus
, NULL
);
461 log_error_errno(r
, "Failed to process requests: %m");
465 r
= sd_bus_wait(bus
, UINT64_MAX
);
467 log_error_errno(r
, "Failed to wait: %m");
477 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*q
= NULL
;
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 (void) sd_bus_send(bus
, q
, NULL
);
494 return INT_TO_PTR(r
);
497 int main(int argc
, char *argv
[]) {
503 test_setup_logging(LOG_INFO
);
505 r
= server_init(&bus
);
507 return log_tests_skipped("Failed to connect to bus");
509 log_info("Initialized...");
511 r
= pthread_create(&c1
, NULL
, client1
, bus
);
515 r
= pthread_create(&c2
, NULL
, client2
, bus
);
521 q
= pthread_join(c1
, &p
);
524 if (PTR_TO_INT(p
) < 0)
527 q
= pthread_join(c2
, &p
);
530 if (PTR_TO_INT(p
) < 0)