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