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