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