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