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