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