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 char *automatic_string_property;
42 uint32_t automatic_integer_property;
45 static int something_handler(sd_bus *bus, sd_bus_message *m, void *userdata) {
46 struct context *c = userdata;
51 r = sd_bus_message_read(m, "s", &s);
54 n = strjoin("<<<", s, ">>>", NULL);
60 log_info("AlterSomething() called, got %s, returning %s", s, n);
62 r = sd_bus_reply_method_return(bus, m, "s", n);
68 static int exit_handler(sd_bus *bus, sd_bus_message *m, void *userdata) {
69 struct context *c = userdata;
74 log_info("Exit called");
76 r = sd_bus_reply_method_return(bus, m, "");
82 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) {
83 struct context *c = userdata;
86 log_info("property get for %s called", property);
88 r = sd_bus_message_append(reply, "s", c->something);
94 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) {
95 struct context *c = userdata;
100 log_info("property set for %s called", property);
102 r = sd_bus_message_read(value, "s", &s);
114 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) {
115 _cleanup_free_ char *s = NULL;
119 assert_se(asprintf(&s, "object %p, path %s", userdata, path) >= 0);
120 r = sd_bus_message_append(reply, "s", s);
123 assert_se(x = startswith(path, "/value/"));
125 assert_se(PTR_TO_UINT(userdata) == 30);
130 static int notify_test(sd_bus *bus, sd_bus_message *m, void *userdata) {
133 assert_se(sd_bus_emit_properties_changed(bus, m->path, "org.freedesktop.systemd.ValueTest", "Value", NULL) >= 0);
135 r = sd_bus_reply_method_return(bus, m, NULL);
141 static int emit_interfaces_added(sd_bus *bus, sd_bus_message *m, void *userdata) {
144 assert_se(sd_bus_emit_interfaces_added(bus, m->path, "org.freedesktop.systemd.test", NULL) >= 0);
146 r = sd_bus_reply_method_return(bus, m, NULL);
152 static int emit_interfaces_removed(sd_bus *bus, sd_bus_message *m, void *userdata) {
155 assert_se(sd_bus_emit_interfaces_removed(bus, m->path, "org.freedesktop.systemd.test", NULL) >= 0);
157 r = sd_bus_reply_method_return(bus, m, NULL);
163 static const sd_bus_vtable vtable[] = {
164 SD_BUS_VTABLE_START(0),
165 SD_BUS_METHOD("AlterSomething", "s", "s", something_handler, 0),
166 SD_BUS_METHOD("Exit", "", "", exit_handler, 0),
167 SD_BUS_WRITABLE_PROPERTY("Something", "s", get_handler, set_handler, 0, 0),
168 SD_BUS_WRITABLE_PROPERTY("AutomaticStringProperty", "s", NULL, NULL, offsetof(struct context, automatic_string_property), 0),
169 SD_BUS_WRITABLE_PROPERTY("AutomaticIntegerProperty", "u", NULL, NULL, offsetof(struct context, automatic_integer_property), 0),
170 SD_BUS_METHOD("NoOperation", NULL, NULL, NULL, 0),
171 SD_BUS_METHOD("EmitInterfacesAdded", NULL, NULL, emit_interfaces_added, 0),
172 SD_BUS_METHOD("EmitInterfacesRemoved", NULL, NULL, emit_interfaces_removed, 0),
176 static const sd_bus_vtable vtable2[] = {
177 SD_BUS_VTABLE_START(0),
178 SD_BUS_METHOD("NotifyTest", "", "", notify_test, 0),
179 SD_BUS_PROPERTY("Value", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
183 static int enumerator_callback(sd_bus *b, const char *path, char ***nodes, void *userdata) {
185 if (object_path_startswith("/value", path))
186 assert_se(*nodes = strv_new("/value/a", "/value/b", "/value/c", NULL));
191 static void *server(void *p) {
192 struct context *c = p;
199 assert_se(sd_id128_randomize(&id) >= 0);
201 assert_se(sd_bus_new(&bus) >= 0);
202 assert_se(sd_bus_set_fd(bus, c->fds[0], c->fds[0]) >= 0);
203 assert_se(sd_bus_set_server(bus, 1, id) >= 0);
205 assert_se(sd_bus_add_object_vtable(bus, "/foo", "org.freedesktop.systemd.test", vtable, c) >= 0);
206 assert_se(sd_bus_add_object_vtable(bus, "/foo", "org.freedesktop.systemd.test2", vtable, c) >= 0);
207 assert_se(sd_bus_add_fallback_vtable(bus, "/value", "org.freedesktop.systemd.ValueTest", vtable2, NULL, UINT_TO_PTR(20)) >= 0);
208 assert_se(sd_bus_add_node_enumerator(bus, "/value", enumerator_callback, NULL) >= 0);
209 assert_se(sd_bus_add_object_manager(bus, "/value") >= 0);
211 assert_se(sd_bus_start(bus) >= 0);
213 log_error("Entering event loop on server");
218 r = sd_bus_process(bus, NULL);
220 log_error("Failed to process requests: %s", strerror(-r));
225 r = sd_bus_wait(bus, (uint64_t) -1);
227 log_error("Failed to wait: %s", strerror(-r));
243 return INT_TO_PTR(r);
246 static int client(struct context *c) {
247 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
248 _cleanup_bus_unref_ sd_bus *bus = NULL;
249 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
253 assert_se(sd_bus_new(&bus) >= 0);
254 assert_se(sd_bus_set_fd(bus, c->fds[1], c->fds[1]) >= 0);
255 assert_se(sd_bus_start(bus) >= 0);
257 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "NoOperation", &error, NULL, NULL);
260 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AlterSomething", &error, &reply, "s", "hallo");
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_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Doesntexist", &error, &reply, "");
272 assert_se(sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.UnknownMethod"));
274 sd_bus_error_free(&error);
276 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AlterSomething", &error, &reply, "as", 1, "hallo");
278 assert_se(sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.InvalidArgs"));
280 sd_bus_error_free(&error);
282 r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, &reply, "s");
285 r = sd_bus_message_read(reply, "s", &s);
287 assert_se(streq(s, "<<<hallo>>>"));
289 sd_bus_message_unref(reply);
292 r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, "s", "test");
295 r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, &reply, "s");
298 r = sd_bus_message_read(reply, "s", &s);
300 assert_se(streq(s, "test"));
302 sd_bus_message_unref(reply);
305 r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AutomaticIntegerProperty", &error, "u", 815);
308 assert_se(c->automatic_integer_property == 815);
310 r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AutomaticStringProperty", &error, "s", "Du Dödel, Du!");
313 assert_se(streq(c->automatic_string_property, "Du Dödel, Du!"));
315 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
318 r = sd_bus_message_read(reply, "s", &s);
322 sd_bus_message_unref(reply);
325 r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/value/xuzz", "org.freedesktop.systemd.ValueTest", "Value", &error, &reply, "s");
328 r = sd_bus_message_read(reply, "s", &s);
330 log_info("read %s", s);
332 sd_bus_message_unref(reply);
335 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
338 r = sd_bus_message_read(reply, "s", &s);
342 sd_bus_message_unref(reply);
345 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
348 r = sd_bus_message_read(reply, "s", &s);
352 sd_bus_message_unref(reply);
355 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
358 r = sd_bus_message_read(reply, "s", &s);
362 sd_bus_message_unref(reply);
365 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", "");
368 bus_message_dump(reply);
370 sd_bus_message_unref(reply);
373 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", "org.freedesktop.systemd.ValueTest2");
375 assert_se(sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.UnknownInterface"));
376 sd_bus_error_free(&error);
378 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", &error, &reply, "");
380 assert_se(sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.UnknownMethod"));
381 sd_bus_error_free(&error);
383 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", &error, &reply, "");
386 bus_message_dump(reply);
388 sd_bus_message_unref(reply);
391 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.systemd.ValueTest", "NotifyTest", &error, NULL, "");
394 r = sd_bus_process(bus, &reply);
397 assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.Properties", "PropertiesChanged"));
398 bus_message_dump(reply);
400 sd_bus_message_unref(reply);
403 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitInterfacesAdded", &error, NULL, "");
406 r = sd_bus_process(bus, &reply);
409 assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded"));
410 bus_message_dump(reply);
412 sd_bus_message_unref(reply);
415 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitInterfacesRemoved", &error, NULL, "");
418 r = sd_bus_process(bus, &reply);
421 assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved"));
422 bus_message_dump(reply);
424 sd_bus_message_unref(reply);
427 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Exit", &error, NULL, "");
435 int main(int argc, char *argv[]) {
443 c.automatic_integer_property = 4711;
444 assert_se(c.automatic_string_property = strdup("dudeldu"));
446 assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, c.fds) >= 0);
448 r = pthread_create(&s, NULL, server, &c);
454 q = pthread_join(s, &p);
461 if (PTR_TO_INT(p) < 0)
462 return PTR_TO_INT(p);
465 free(c.automatic_string_property);