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