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/>.
34 #include "bus-internal.h"
35 #include "bus-message.h"
41 * automatic properties
42 * node hierarchy updates during dispatching
43 * emit_interfaces_added/emit_interfaces_removed
53 static int something_handler(sd_bus *bus, sd_bus_message *m, void *userdata) {
54 struct context *c = userdata;
59 r = sd_bus_message_read(m, "s", &s);
62 n = strjoin("<<<", s, ">>>", NULL);
68 log_info("AlterSomething() called, got %s, returning %s", s, n);
70 r = sd_bus_reply_method_return(bus, m, "s", n);
76 static int exit_handler(sd_bus *bus, sd_bus_message *m, void *userdata) {
77 struct context *c = userdata;
82 log_info("Exit called");
84 r = sd_bus_reply_method_return(bus, m, "");
90 static int get_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, sd_bus_error *error, void *userdata) {
91 struct context *c = userdata;
94 log_info("property get for %s called", property);
96 r = sd_bus_message_append(reply, "s", c->something);
102 static int set_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, sd_bus_error *error, void *userdata) {
103 struct context *c = userdata;
108 log_info("property set for %s called", property);
110 r = sd_bus_message_read(value, "s", &s);
122 static int value_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, sd_bus_error *error, void *userdata) {
123 _cleanup_free_ char *s = NULL;
127 assert_se(asprintf(&s, "object %p, path %s", userdata, path) >= 0);
128 r = sd_bus_message_append(reply, "s", s);
131 assert_se(x = startswith(path, "/value/"));
133 assert_se(PTR_TO_UINT(userdata) == 30);
138 static int notify_test(sd_bus *bus, sd_bus_message *m, void *userdata) {
141 assert_se(sd_bus_emit_properties_changed(bus, m->path, "org.freedesktop.systemd.ValueTest", "Value", NULL) >= 0);
143 r = sd_bus_reply_method_return(bus, m, NULL);
149 static const sd_bus_vtable vtable[] = {
150 SD_BUS_VTABLE_START(0),
151 SD_BUS_METHOD("AlterSomething", "s", "s", 0, something_handler),
152 SD_BUS_METHOD("Exit", "", "", 0, exit_handler),
153 SD_BUS_WRITABLE_PROPERTY("Something", "s", get_handler, set_handler, 0, 0),
157 static const sd_bus_vtable vtable2[] = {
158 SD_BUS_VTABLE_START(0),
159 SD_BUS_METHOD("NotifyTest", "", "", 0, notify_test),
160 SD_BUS_PROPERTY("Value", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
164 static int enumerator_callback(sd_bus *b, const char *path, char ***nodes, void *userdata) {
166 if (object_path_startswith("/value", path))
167 assert_se(*nodes = strv_new("/value/a", "/value/b", "/value/c", NULL));
172 static void *server(void *p) {
173 struct context *c = p;
180 assert_se(sd_id128_randomize(&id) >= 0);
182 assert_se(sd_bus_new(&bus) >= 0);
183 assert_se(sd_bus_set_fd(bus, c->fds[0], c->fds[0]) >= 0);
184 assert_se(sd_bus_set_server(bus, 1, id) >= 0);
186 assert_se(sd_bus_add_object_vtable(bus, "/foo", "org.freedesktop.systemd.test", vtable, c) >= 0);
187 assert_se(sd_bus_add_object_vtable(bus, "/foo", "org.freedesktop.systemd.test2", vtable, c) >= 0);
188 assert_se(sd_bus_add_fallback_vtable(bus, "/value", "org.freedesktop.systemd.ValueTest", vtable2, NULL, UINT_TO_PTR(20)) >= 0);
189 assert_se(sd_bus_add_node_enumerator(bus, "/value", enumerator_callback, NULL) >= 0);
190 assert_se(sd_bus_add_object_manager(bus, "/value") >= 0);
192 assert_se(sd_bus_start(bus) >= 0);
194 log_error("Entering event loop on server");
199 r = sd_bus_process(bus, NULL);
201 log_error("Failed to process requests: %s", strerror(-r));
206 r = sd_bus_wait(bus, (uint64_t) -1);
208 log_error("Failed to wait: %s", strerror(-r));
224 return INT_TO_PTR(r);
227 static int client(struct context *c) {
228 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
229 _cleanup_bus_unref_ sd_bus *bus = NULL;
230 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
234 assert_se(sd_bus_new(&bus) >= 0);
235 assert_se(sd_bus_set_fd(bus, c->fds[1], c->fds[1]) >= 0);
236 assert_se(sd_bus_start(bus) >= 0);
238 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AlterSomething", &error, &reply, "s", "hallo");
241 r = sd_bus_message_read(reply, "s", &s);
243 assert_se(streq(s, "<<<hallo>>>"));
245 sd_bus_message_unref(reply);
248 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Doesntexist", &error, &reply, "");
250 assert_se(sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.UnknownMethod"));
252 sd_bus_error_free(&error);
254 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AlterSomething", &error, &reply, "as", 1, "hallo");
256 assert_se(sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.InvalidArgs"));
258 sd_bus_error_free(&error);
260 r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, &reply, "s");
263 r = sd_bus_message_read(reply, "s", &s);
265 assert_se(streq(s, "<<<hallo>>>"));
267 sd_bus_message_unref(reply);
270 r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, "s", "test");
273 r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, &reply, "s");
276 r = sd_bus_message_read(reply, "s", &s);
278 assert_se(streq(s, "test"));
280 sd_bus_message_unref(reply);
283 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
286 r = sd_bus_message_read(reply, "s", &s);
290 sd_bus_message_unref(reply);
293 r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/value/xuzz", "org.freedesktop.systemd.ValueTest", "Value", &error, &reply, "s");
296 r = sd_bus_message_read(reply, "s", &s);
298 log_info("read %s", s);
300 sd_bus_message_unref(reply);
303 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
306 r = sd_bus_message_read(reply, "s", &s);
310 sd_bus_message_unref(reply);
313 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
316 r = sd_bus_message_read(reply, "s", &s);
320 sd_bus_message_unref(reply);
323 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
326 r = sd_bus_message_read(reply, "s", &s);
330 sd_bus_message_unref(reply);
333 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", "");
336 bus_message_dump(reply);
338 sd_bus_message_unref(reply);
341 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", "org.freedesktop.systemd.ValueTest2");
343 assert_se(sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.UnknownInterface"));
344 sd_bus_error_free(&error);
346 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", &error, &reply, "");
348 assert_se(sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.UnknownMethod"));
349 sd_bus_error_free(&error);
351 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", &error, &reply, "");
354 bus_message_dump(reply);
356 sd_bus_message_unref(reply);
359 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.systemd.ValueTest", "NotifyTest", &error, NULL, "");
362 r = sd_bus_process(bus, &reply);
365 assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.Properties", "PropertiesChanged"));
366 bus_message_dump(reply);
368 sd_bus_message_unref(reply);
371 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Exit", &error, NULL, "");
379 int main(int argc, char *argv[]) {
387 assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, c.fds) >= 0);
389 r = pthread_create(&s, NULL, server, &c);
395 q = pthread_join(s, &p);
402 if (PTR_TO_INT(p) < 0)
403 return PTR_TO_INT(p);