]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-bus/test-bus-chat.c
nspawn: Make parameter provided_mac a const for setup_veth()
[thirdparty/systemd.git] / src / libsystemd / sd-bus / test-bus-chat.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
89ffcd2a 2
cf0fbc49 3#include <fcntl.h>
89ffcd2a 4#include <pthread.h>
cf0fbc49 5#include <stdlib.h>
e3017af9 6#include <unistd.h>
89ffcd2a 7
89ffcd2a 8#include "sd-bus.h"
07630cea 9
b5efdb8a 10#include "alloc-util.h"
e3017af9 11#include "bus-error.h"
392d5b37 12#include "bus-internal.h"
07630cea 13#include "bus-match.h"
4bbccb02 14#include "errno-util.h"
cf0fbc49 15#include "fd-util.h"
f97b34a6 16#include "format-util.h"
07630cea
LP
17#include "log.h"
18#include "macro.h"
6969a671 19#include "string-util.h"
317bb217 20#include "tests.h"
392d5b37 21
19070062 22static int match_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
85bc6b05
EM
23 log_info("Match triggered! destination=%s interface=%s member=%s",
24 strna(sd_bus_message_get_destination(m)),
25 strna(sd_bus_message_get_interface(m)),
26 strna(sd_bus_message_get_member(m)));
392d5b37
LP
27 return 0;
28}
89ffcd2a 29
19070062 30static int object_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
a652755d
LP
31 int r;
32
eb01ba5d 33 if (sd_bus_message_is_method_error(m, NULL))
a652755d
LP
34 return 0;
35
36 if (sd_bus_message_is_method_call(m, "org.object.test", "Foobar")) {
a652755d
LP
37 log_info("Invoked Foobar() on %s", sd_bus_message_get_path(m));
38
df2d202e 39 r = sd_bus_reply_method_return(m, NULL);
f647962d
MS
40 if (r < 0)
41 return log_error_errno(r, "Failed to send reply: %m");
a652755d
LP
42
43 return 1;
44 }
45
46 return 0;
47}
48
4b7604af
LP
49static int server_init(sd_bus **ret_bus) {
50 _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
51 const char *unique, *desc;
d728d708 52 sd_id128_t id;
89ffcd2a
LP
53 int r;
54
4b7604af 55 assert_se(ret_bus);
89ffcd2a 56
56fbd718 57 r = sd_bus_open_user_with_description(&bus, "my bus!");
4b7604af
LP
58 if (r < 0)
59 return log_error_errno(r, "Failed to connect to user bus: %m");
89ffcd2a 60
5c302692 61 r = sd_bus_get_bus_id(bus, &id);
4b7604af
LP
62 if (r < 0)
63 return log_error_errno(r, "Failed to get server ID: %m");
d728d708 64
20902f3e 65 r = sd_bus_get_unique_name(bus, &unique);
4b7604af
LP
66 if (r < 0)
67 return log_error_errno(r, "Failed to get unique name: %m");
20902f3e 68
90e207e4 69 assert_se(sd_bus_get_description(bus, &desc) >= 0);
56fbd718
ZJS
70 assert_se(streq(desc, "my bus!"));
71
d728d708 72 log_info("Peer ID is " SD_ID128_FORMAT_STR ".", SD_ID128_FORMAT_VAL(id));
20902f3e 73 log_info("Unique ID: %s", unique);
d728d708 74 log_info("Can send file handles: %i", sd_bus_can_send(bus, 'h'));
d728d708 75
89ffcd2a 76 r = sd_bus_request_name(bus, "org.freedesktop.systemd.test", 0);
4b7604af
LP
77 if (r < 0)
78 return log_error_errno(r, "Failed to acquire name: %m");
89ffcd2a 79
19befb2d 80 r = sd_bus_add_fallback(bus, NULL, "/foo/bar", object_callback, NULL);
4b7604af
LP
81 if (r < 0)
82 return log_error_errno(r, "Failed to add object: %m");
a652755d 83
75152a4d 84 r = sd_bus_match_signal(bus, NULL, NULL, NULL, "foo.bar", "Notify", match_callback, NULL);
4b7604af
LP
85 if (r < 0)
86 return log_error_errno(r, "Failed to request match: %m");
392d5b37 87
85bc6b05 88 r = sd_bus_match_signal(bus, NULL, NULL, NULL, "foo.bar", "NotifyTo", match_callback, NULL);
4b7604af
LP
89 if (r < 0)
90 return log_error_errno(r, "Failed to request match: %m");
85bc6b05 91
19befb2d 92 r = sd_bus_add_match(bus, NULL, "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged'", match_callback, NULL);
4b7604af
LP
93 if (r < 0)
94 return log_error_errno(r, "Failed to add match: %m");
392d5b37 95
fc561c8e 96 bus_match_dump(stdout, &bus->match_callbacks, 0);
392d5b37 97
4b7604af 98 *ret_bus = TAKE_PTR(bus);
89ffcd2a 99 return 0;
89ffcd2a
LP
100}
101
4b7604af
LP
102static int server(sd_bus *_bus) {
103 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = ASSERT_PTR(_bus);
e3017af9 104 bool client1_gone = false, client2_gone = false;
4b7604af 105 int r;
89ffcd2a 106
e3017af9 107 while (!client1_gone || !client2_gone) {
4afd3348 108 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
2571ead1 109 pid_t pid = 0;
4a875b61 110 const char *label = NULL;
89ffcd2a
LP
111
112 r = sd_bus_process(bus, &m);
4b7604af
LP
113 if (r < 0)
114 return log_error_errno(r, "Failed to process requests: %m");
89ffcd2a 115 if (r == 0) {
f5fbe71d 116 r = sd_bus_wait(bus, UINT64_MAX);
4b7604af
LP
117 if (r < 0)
118 return log_error_errno(r, "Failed to wait: %m");
89ffcd2a
LP
119
120 continue;
121 }
e3017af9
LP
122 if (!m)
123 continue;
124
4b7604af
LP
125 (void) sd_bus_creds_get_pid(sd_bus_message_get_creds(m), &pid);
126 (void) sd_bus_creds_get_selinux_context(sd_bus_message_get_creds(m), &label);
127
de0671ee 128 log_info("Got message! member=%s pid="PID_FMT" label=%s",
4a875b61 129 strna(sd_bus_message_get_member(m)),
de0671ee 130 pid,
4a875b61 131 strna(label));
4b7604af 132
2b4a65b6 133 /* sd_bus_message_dump(m); */
89ffcd2a
LP
134 /* sd_bus_message_rewind(m, true); */
135
136 if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "LowerCase")) {
137 const char *hello;
138 _cleanup_free_ char *lowercase = NULL;
139
140 r = sd_bus_message_read(m, "s", &hello);
4b7604af
LP
141 if (r < 0)
142 return log_error_errno(r, "Failed to get parameter: %m");
89ffcd2a 143
89ffcd2a 144 lowercase = strdup(hello);
4b7604af
LP
145 if (!lowercase)
146 return log_oom();
89ffcd2a
LP
147
148 ascii_strlower(lowercase);
149
df2d202e 150 r = sd_bus_reply_method_return(m, "s", lowercase);
4b7604af
LP
151 if (r < 0)
152 return log_error_errno(r, "Failed to send reply: %m");
153
e3017af9
LP
154 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient1")) {
155
df2d202e 156 r = sd_bus_reply_method_return(m, NULL);
4b7604af
LP
157 if (r < 0)
158 return log_error_errno(r, "Failed to send reply: %m");
e3017af9
LP
159
160 client1_gone = true;
161 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient2")) {
162
df2d202e 163 r = sd_bus_reply_method_return(m, NULL);
4b7604af
LP
164 if (r < 0)
165 return log_error_errno(r, "Failed to send reply: %m");
e3017af9
LP
166
167 client2_gone = true;
168 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Slow")) {
169
b7f247e0
LP
170 sleep(1);
171
df2d202e 172 r = sd_bus_reply_method_return(m, NULL);
4b7604af
LP
173 if (r < 0)
174 return log_error_errno(r, "Failed to send reply: %m");
e3017af9 175
2c93b4ef
LP
176 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "FileDescriptor")) {
177 int fd;
178 static const char x = 'X';
179
180 r = sd_bus_message_read(m, "h", &fd);
4b7604af
LP
181 if (r < 0)
182 return log_error_errno(r, "Failed to get parameter: %m");
2c93b4ef 183
5a330cda
ZJS
184 log_info("Received fd=%d", fd);
185
2c93b4ef 186 if (write(fd, &x, 1) < 0) {
4b7604af 187 r = log_error_errno(errno, "Failed to write to fd: %m");
03e334a1 188 safe_close(fd);
4b7604af 189 return r;
2c93b4ef
LP
190 }
191
df2d202e 192 r = sd_bus_reply_method_return(m, NULL);
4b7604af
LP
193 if (r < 0)
194 return log_error_errno(r, "Failed to send reply: %m");
2c93b4ef 195
e3017af9 196 } else if (sd_bus_message_is_method_call(m, NULL, NULL)) {
89ffcd2a 197
d4100e24 198 r = sd_bus_reply_method_error(
df2d202e 199 m,
14c24659 200 &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method."));
4b7604af
LP
201 if (r < 0)
202 return log_error_errno(r, "Failed to send reply: %m");
89ffcd2a
LP
203 }
204 }
205
4b7604af 206 return 0;
89ffcd2a
LP
207}
208
f2a3de01 209static void* client1(void *p) {
4afd3348
LP
210 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
211 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
212 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
89ffcd2a
LP
213 const char *hello;
214 int r;
19ee48a6 215 _cleanup_close_pair_ int pp[2] = PIPE_EBADF;
2c93b4ef 216 char x;
89ffcd2a
LP
217
218 r = sd_bus_open_user(&bus);
219 if (r < 0) {
da927ba9 220 log_error_errno(r, "Failed to connect to user bus: %m");
89ffcd2a
LP
221 goto finish;
222 }
223
d4100e24 224 r = sd_bus_call_method(
89ffcd2a
LP
225 bus,
226 "org.freedesktop.systemd.test",
227 "/",
228 "org.freedesktop.systemd.test",
229 "LowerCase",
d4100e24
LP
230 &error,
231 &reply,
232 "s",
233 "HELLO");
89ffcd2a 234 if (r < 0) {
da927ba9 235 log_error_errno(r, "Failed to issue method call: %m");
89ffcd2a
LP
236 goto finish;
237 }
238
239 r = sd_bus_message_read(reply, "s", &hello);
240 if (r < 0) {
da927ba9 241 log_error_errno(r, "Failed to get string: %m");
89ffcd2a
LP
242 goto finish;
243 }
244
0c0cdb06 245 assert_se(streq(hello, "hello"));
89ffcd2a 246
2c93b4ef 247 if (pipe2(pp, O_CLOEXEC|O_NONBLOCK) < 0) {
d7a0f1f4 248 r = log_error_errno(errno, "Failed to allocate pipe: %m");
2c93b4ef
LP
249 goto finish;
250 }
251
5a330cda
ZJS
252 log_info("Sending fd=%d", pp[1]);
253
b7f247e0 254 r = sd_bus_call_method(
2c93b4ef
LP
255 bus,
256 "org.freedesktop.systemd.test",
257 "/",
258 "org.freedesktop.systemd.test",
259 "FileDescriptor",
b7f247e0
LP
260 &error,
261 NULL,
262 "h",
263 pp[1]);
2c93b4ef 264 if (r < 0) {
da927ba9 265 log_error_errno(r, "Failed to issue method call: %m");
2c93b4ef
LP
266 goto finish;
267 }
268
269 errno = 0;
270 if (read(pp[0], &x, 1) <= 0) {
f69ae858 271 log_error("Failed to read from pipe: %s", STRERROR_OR_EOF(errno));
2c93b4ef
LP
272 goto finish;
273 }
274
89ffcd2a
LP
275 r = 0;
276
277finish:
278 if (bus) {
b9c54c46 279 _cleanup_(sd_bus_message_unrefp) sd_bus_message *q = NULL;
89ffcd2a
LP
280
281 r = sd_bus_message_new_method_call(
282 bus,
151b9b96 283 &q,
89ffcd2a
LP
284 "org.freedesktop.systemd.test",
285 "/",
286 "org.freedesktop.systemd.test",
151b9b96 287 "ExitClient1");
b7f247e0 288 if (r < 0)
da927ba9 289 log_error_errno(r, "Failed to allocate method call: %m");
b7f247e0
LP
290 else
291 sd_bus_send(bus, q, NULL);
89ffcd2a 292
89ffcd2a
LP
293 }
294
e3017af9
LP
295 return INT_TO_PTR(r);
296}
297
19070062 298static int quit_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
e3017af9
LP
299 bool *x = userdata;
300
9eec7d12 301 log_error_errno(sd_bus_message_get_errno(m), "Quit callback: %m");
e3017af9
LP
302
303 *x = 1;
304 return 1;
305}
306
f2a3de01 307static void* client2(void *p) {
4afd3348
LP
308 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
309 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
310 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
e3017af9 311 bool quit = false;
b9bf7e2b
LP
312 const char *mid;
313 int r;
e3017af9
LP
314
315 r = sd_bus_open_user(&bus);
316 if (r < 0) {
da927ba9 317 log_error_errno(r, "Failed to connect to user bus: %m");
e3017af9
LP
318 goto finish;
319 }
320
a652755d
LP
321 r = sd_bus_message_new_method_call(
322 bus,
151b9b96 323 &m,
a652755d
LP
324 "org.freedesktop.systemd.test",
325 "/foo/bar/waldo/piep",
326 "org.object.test",
151b9b96 327 "Foobar");
a652755d 328 if (r < 0) {
da927ba9 329 log_error_errno(r, "Failed to allocate method call: %m");
a652755d
LP
330 goto finish;
331 }
332
333 r = sd_bus_send(bus, m, NULL);
334 if (r < 0) {
2a03b9ed 335 log_error("Failed to issue method call: %s", bus_error_message(&error, r));
a652755d
LP
336 goto finish;
337 }
338
0e851143 339 m = sd_bus_message_unref(m);
a652755d 340
392d5b37
LP
341 r = sd_bus_message_new_signal(
342 bus,
151b9b96 343 &m,
392d5b37
LP
344 "/foobar",
345 "foo.bar",
151b9b96 346 "Notify");
392d5b37 347 if (r < 0) {
da927ba9 348 log_error_errno(r, "Failed to allocate signal: %m");
392d5b37
LP
349 goto finish;
350 }
351
352 r = sd_bus_send(bus, m, NULL);
353 if (r < 0) {
2a03b9ed 354 log_error("Failed to issue signal: %s", bus_error_message(&error, r));
392d5b37
LP
355 goto finish;
356 }
357
0e851143 358 m = sd_bus_message_unref(m);
392d5b37 359
85bc6b05
EM
360 r = sd_bus_message_new_signal_to(
361 bus,
362 &m,
363 "org.freedesktop.systemd.test",
364 "/foobar",
365 "foo.bar",
366 "NotifyTo");
367 if (r < 0) {
368 log_error_errno(r, "Failed to allocate signal to: %m");
369 goto finish;
370 }
371
372 r = sd_bus_send(bus, m, NULL);
373 if (r < 0) {
374 log_error("Failed to issue signal to: %s", bus_error_message(&error, r));
375 goto finish;
376 }
377
378 m = sd_bus_message_unref(m);
379
b9bf7e2b
LP
380 r = sd_bus_message_new_method_call(
381 bus,
151b9b96 382 &m,
b9bf7e2b
LP
383 "org.freedesktop.systemd.test",
384 "/",
385 "org.freedesktop.DBus.Peer",
151b9b96 386 "GetMachineId");
b9bf7e2b 387 if (r < 0) {
da927ba9 388 log_error_errno(r, "Failed to allocate method call: %m");
b9bf7e2b
LP
389 goto finish;
390 }
391
c49b30a2 392 r = sd_bus_call(bus, m, 0, &error, &reply);
b9bf7e2b 393 if (r < 0) {
2a03b9ed 394 log_error("Failed to issue method call: %s", bus_error_message(&error, r));
b9bf7e2b
LP
395 goto finish;
396 }
397
398 r = sd_bus_message_read(reply, "s", &mid);
399 if (r < 0) {
da927ba9 400 log_error_errno(r, "Failed to parse machine ID: %m");
b9bf7e2b
LP
401 goto finish;
402 }
403
404 log_info("Machine ID is %s.", mid);
405
0e851143 406 m = sd_bus_message_unref(m);
b9bf7e2b 407
e3017af9
LP
408 r = sd_bus_message_new_method_call(
409 bus,
151b9b96 410 &m,
e3017af9
LP
411 "org.freedesktop.systemd.test",
412 "/",
413 "org.freedesktop.systemd.test",
151b9b96 414 "Slow");
e3017af9 415 if (r < 0) {
da927ba9 416 log_error_errno(r, "Failed to allocate method call: %m");
e3017af9
LP
417 goto finish;
418 }
419
0e851143 420 reply = sd_bus_message_unref(reply);
b9bf7e2b 421
c49b30a2 422 r = sd_bus_call(bus, m, 200 * USEC_PER_MSEC, &error, &reply);
e3017af9 423 if (r < 0)
2a03b9ed 424 log_info("Failed to issue method call: %s", bus_error_message(&error, r));
e3017af9
LP
425 else
426 log_info("Slow call succeed.");
427
0e851143 428 m = sd_bus_message_unref(m);
e3017af9
LP
429
430 r = sd_bus_message_new_method_call(
431 bus,
151b9b96 432 &m,
e3017af9
LP
433 "org.freedesktop.systemd.test",
434 "/",
435 "org.freedesktop.systemd.test",
151b9b96 436 "Slow");
e3017af9 437 if (r < 0) {
da927ba9 438 log_error_errno(r, "Failed to allocate method call: %m");
e3017af9
LP
439 goto finish;
440 }
441
19befb2d 442 r = sd_bus_call_async(bus, NULL, m, quit_callback, &quit, 200 * USEC_PER_MSEC);
e3017af9 443 if (r < 0) {
2a03b9ed 444 log_info("Failed to issue method call: %s", bus_error_message(&error, r));
e3017af9
LP
445 goto finish;
446 }
447
448 while (!quit) {
449 r = sd_bus_process(bus, NULL);
450 if (r < 0) {
da927ba9 451 log_error_errno(r, "Failed to process requests: %m");
e3017af9
LP
452 goto finish;
453 }
454 if (r == 0) {
f5fbe71d 455 r = sd_bus_wait(bus, UINT64_MAX);
e3017af9 456 if (r < 0) {
da927ba9 457 log_error_errno(r, "Failed to wait: %m");
e3017af9
LP
458 goto finish;
459 }
460 }
461 }
462
463 r = 0;
464
465finish:
466 if (bus) {
b9c54c46 467 _cleanup_(sd_bus_message_unrefp) sd_bus_message *q = NULL;
e3017af9
LP
468
469 r = sd_bus_message_new_method_call(
470 bus,
151b9b96 471 &q,
e3017af9
LP
472 "org.freedesktop.systemd.test",
473 "/",
474 "org.freedesktop.systemd.test",
151b9b96 475 "ExitClient2");
e3017af9 476 if (r < 0) {
da927ba9 477 log_error_errno(r, "Failed to allocate method call: %m");
e3017af9
LP
478 goto finish;
479 }
480
0e851143 481 (void) sd_bus_send(bus, q, NULL);
e3017af9
LP
482 }
483
e3017af9 484 return INT_TO_PTR(r);
89ffcd2a
LP
485}
486
487int main(int argc, char *argv[]) {
e3017af9 488 pthread_t c1, c2;
89ffcd2a
LP
489 sd_bus *bus;
490 void *p;
491 int q, r;
492
6d7c4033
ZJS
493 test_setup_logging(LOG_INFO);
494
89ffcd2a 495 r = server_init(&bus);
317bb217
ZJS
496 if (r < 0)
497 return log_tests_skipped("Failed to connect to bus");
89ffcd2a 498
e3017af9
LP
499 log_info("Initialized...");
500
501 r = pthread_create(&c1, NULL, client1, bus);
502 if (r != 0)
89ffcd2a 503 return EXIT_FAILURE;
89ffcd2a 504
e3017af9
LP
505 r = pthread_create(&c2, NULL, client2, bus);
506 if (r != 0)
507 return EXIT_FAILURE;
89ffcd2a 508
e3017af9
LP
509 r = server(bus);
510
511 q = pthread_join(c1, &p);
512 if (q != 0)
513 return EXIT_FAILURE;
2181a7f5
LP
514 if (PTR_TO_INT(p) < 0)
515 return EXIT_FAILURE;
516
e3017af9 517 q = pthread_join(c2, &p);
89ffcd2a
LP
518 if (q != 0)
519 return EXIT_FAILURE;
2181a7f5
LP
520 if (PTR_TO_INT(p) < 0)
521 return EXIT_FAILURE;
522
89ffcd2a
LP
523 if (r < 0)
524 return EXIT_FAILURE;
525
526 return EXIT_SUCCESS;
527}