1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
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.
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.
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/>.
32 #include "bus-message.h"
33 #include "bus-error.h"
35 static int object_callback(sd_bus *bus, int error, sd_bus_message *m, void *userdata) {
43 if (sd_bus_message_is_method_call(m, "org.object.test", "Foobar")) {
44 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
46 log_info("Invoked Foobar() on %s", sd_bus_message_get_path(m));
48 r = sd_bus_message_new_method_return(bus, m, &reply);
50 log_error("Failed to allocate return: %s", strerror(-r));
54 r = sd_bus_send(bus, reply, NULL);
56 log_error("Failed to send reply: %s", strerror(-r));
66 static int server_init(sd_bus **_bus) {
74 r = sd_bus_open_user(&bus);
76 log_error("Failed to connect to user bus: %s", strerror(-r));
80 r = sd_bus_get_peer(bus, &id);
82 log_error("Failed to get peer ID: %s", strerror(-r));
86 r = sd_bus_get_unique_name(bus, &unique);
88 log_error("Failed to get unique name: %s", strerror(-r));
92 log_info("Peer ID is " SD_ID128_FORMAT_STR ".", SD_ID128_FORMAT_VAL(id));
93 log_info("Unique ID: %s", unique);
94 log_info("Can send file handles: %i", sd_bus_can_send(bus, 'h'));
96 r = sd_bus_request_name(bus, "org.freedesktop.systemd.test", 0);
98 log_error("Failed to acquire name: %s", strerror(-r));
102 r = sd_bus_add_fallback(bus, "/foo/bar", object_callback, NULL);
104 log_error("Failed to add object: %s", strerror(-r));
118 static int server(sd_bus *bus) {
120 bool client1_gone = false, client2_gone = false;
122 while (!client1_gone || !client2_gone) {
123 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
126 r = sd_bus_process(bus, &m);
128 log_error("Failed to process requests: %s", strerror(-r));
133 r = sd_bus_wait(bus, (uint64_t) -1);
135 log_error("Failed to wait: %s", strerror(-r));
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)));
147 /* bus_message_dump(m); */
148 /* sd_bus_message_rewind(m, true); */
150 if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "LowerCase")) {
152 _cleanup_free_ char *lowercase = NULL;
154 r = sd_bus_message_read(m, "s", &hello);
156 log_error("Failed to get parameter: %s", strerror(-r));
160 r = sd_bus_message_new_method_return(bus, m, &reply);
162 log_error("Failed to allocate return: %s", strerror(-r));
166 lowercase = strdup(hello);
172 ascii_strlower(lowercase);
174 r = sd_bus_message_append(reply, "s", lowercase);
176 log_error("Failed to append message: %s", strerror(-r));
179 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient1")) {
181 r = sd_bus_message_new_method_return(bus, m, &reply);
183 log_error("Failed to allocate return: %s", strerror(-r));
188 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient2")) {
190 r = sd_bus_message_new_method_return(bus, m, &reply);
192 log_error("Failed to allocate return: %s", strerror(-r));
197 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Slow")) {
199 r = sd_bus_message_new_method_return(bus, m, &reply);
201 log_error("Failed to allocate return: %s", strerror(-r));
207 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "FileDescriptor")) {
209 static const char x = 'X';
211 r = sd_bus_message_read(m, "h", &fd);
213 log_error("Failed to get parameter: %s", strerror(-r));
217 if (write(fd, &x, 1) < 0) {
218 log_error("Failed to write to fd: %m");
219 close_nointr_nofail(fd);
223 close_nointr_nofail(fd);
225 r = sd_bus_message_new_method_return(bus, m, &reply);
227 log_error("Failed to allocate return: %s", strerror(-r));
231 } else if (sd_bus_message_is_method_call(m, NULL, NULL)) {
232 const sd_bus_error e = SD_BUS_ERROR_INIT_CONST("org.freedesktop.DBus.Error.UnknownMethod", "Unknown method.");
234 r = sd_bus_message_new_method_error(bus, m, &e, &reply);
236 log_error("Failed to allocate return: %s", strerror(-r));
242 r = sd_bus_send(bus, reply, NULL);
244 log_error("Failed to send reply: %s", strerror(-r));
248 /* log_info("Sent"); */
249 /* bus_message_dump(reply); */
250 /* sd_bus_message_rewind(reply, true); */
265 static void* client1(void*p) {
266 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
268 sd_bus_error error = SD_BUS_ERROR_INIT;
271 int pp[2] = { -1, -1 };
274 r = sd_bus_open_user(&bus);
276 log_error("Failed to connect to user bus: %s", strerror(-r));
280 r = sd_bus_message_new_method_call(
282 "org.freedesktop.systemd.test",
284 "org.freedesktop.systemd.test",
288 log_error("Failed to allocate method call: %s", strerror(-r));
292 r = sd_bus_message_append(m, "s", "HELLO");
294 log_error("Failed to append string: %s", strerror(-r));
298 r = sd_bus_send_with_reply_and_block(bus, m, 0, &error, &reply);
300 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
304 r = sd_bus_message_read(reply, "s", &hello);
306 log_error("Failed to get string: %s", strerror(-r));
310 assert(streq(hello, "hello"));
312 if (pipe2(pp, O_CLOEXEC|O_NONBLOCK) < 0) {
313 log_error("Failed to allocate pipe: %m");
318 sd_bus_message_unref(m);
320 r = sd_bus_message_new_method_call(
322 "org.freedesktop.systemd.test",
324 "org.freedesktop.systemd.test",
328 log_error("Failed to allocate method call: %s", strerror(-r));
332 r = sd_bus_message_append(m, "h", pp[1]);
334 log_error("Failed to append string: %s", strerror(-r));
338 sd_bus_message_unref(reply);
340 r = sd_bus_send_with_reply_and_block(bus, m, 0, &error, &reply);
342 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
347 if (read(pp[0], &x, 1) <= 0) {
348 log_error("Failed to read from pipe: %s", errno ? strerror(errno) : "early read");
356 _cleanup_bus_message_unref_ sd_bus_message *q;
358 r = sd_bus_message_new_method_call(
360 "org.freedesktop.systemd.test",
362 "org.freedesktop.systemd.test",
366 log_error("Failed to allocate method call: %s", strerror(-r));
370 sd_bus_send(bus, q, NULL);
375 sd_bus_error_free(&error);
379 return INT_TO_PTR(r);
382 static int quit_callback(sd_bus *b, int ret, sd_bus_message *m, void *userdata) {
385 log_error("Quit callback: %s", strerror(ret));
391 static void* client2(void*p) {
392 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
394 sd_bus_error error = SD_BUS_ERROR_INIT;
399 r = sd_bus_open_user(&bus);
401 log_error("Failed to connect to user bus: %s", strerror(-r));
405 r = sd_bus_message_new_method_call(
407 "org.freedesktop.systemd.test",
408 "/foo/bar/waldo/piep",
413 log_error("Failed to allocate method call: %s", strerror(-r));
417 r = sd_bus_send(bus, m, NULL);
419 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
423 sd_bus_message_unref(m);
426 r = sd_bus_message_new_method_call(
428 "org.freedesktop.systemd.test",
430 "org.freedesktop.DBus.Peer",
434 log_error("Failed to allocate method call: %s", strerror(-r));
438 r = sd_bus_send_with_reply_and_block(bus, m, 0, &error, &reply);
440 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
444 r = sd_bus_message_read(reply, "s", &mid);
446 log_error("Failed to parse machine ID: %s", strerror(-r));
450 log_info("Machine ID is %s.", mid);
452 sd_bus_message_unref(m);
455 r = sd_bus_message_new_method_call(
457 "org.freedesktop.systemd.test",
459 "org.freedesktop.systemd.test",
463 log_error("Failed to allocate method call: %s", strerror(-r));
467 sd_bus_message_unref(reply);
470 r = sd_bus_send_with_reply_and_block(bus, m, 200 * USEC_PER_MSEC, &error, &reply);
472 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
474 log_info("Slow call succeed.");
476 sd_bus_message_unref(m);
479 r = sd_bus_message_new_method_call(
481 "org.freedesktop.systemd.test",
483 "org.freedesktop.systemd.test",
487 log_error("Failed to allocate method call: %s", strerror(-r));
491 r = sd_bus_send_with_reply(bus, m, quit_callback, &quit, 200 * USEC_PER_MSEC, NULL);
493 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
498 r = sd_bus_process(bus, NULL);
500 log_error("Failed to process requests: %s", strerror(-r));
504 r = sd_bus_wait(bus, (uint64_t) -1);
506 log_error("Failed to wait: %s", strerror(-r));
516 _cleanup_bus_message_unref_ sd_bus_message *q;
518 r = sd_bus_message_new_method_call(
520 "org.freedesktop.systemd.test",
522 "org.freedesktop.systemd.test",
526 log_error("Failed to allocate method call: %s", strerror(-r));
530 sd_bus_send(bus, q, NULL);
535 sd_bus_error_free(&error);
536 return INT_TO_PTR(r);
539 int main(int argc, char *argv[]) {
545 r = server_init(&bus);
549 log_info("Initialized...");
551 r = pthread_create(&c1, NULL, client1, bus);
555 r = pthread_create(&c2, NULL, client2, bus);
561 q = pthread_join(c1, &p);
564 q = pthread_join(c2, &p);