chiark / gitweb /
bus: if a a Set() vtable callback of a writable is left NULL, try to do the right...
authorLennart Poettering <lennart@poettering.net>
Fri, 11 Oct 2013 18:02:16 +0000 (20:02 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 11 Oct 2013 18:03:19 +0000 (20:03 +0200)
TODO
src/libsystemd-bus/sd-bus.c
src/libsystemd-bus/test-bus-objects.c
src/systemd/sd-bus.h

diff --git a/TODO b/TODO
index 6847217..4a498b9 100644 (file)
--- a/TODO
+++ b/TODO
@@ -52,6 +52,8 @@ CGroup Rework Completion:
 
 Features:
 
+* Add a new Distribute=$NUMBER key to socket units that makes use of SO_REUSEPORT to distribute network traffic on $NUMBER instances
+
 * tmpfiles: when applying ownership to /run/log/journal also do this for the journal fails contained in it
 
 * rework list.h to use typeof() and thus simplify most linked list macros by not requring the type to be specified
index 3fd5186..cebb073 100644 (file)
@@ -2089,11 +2089,11 @@ static int method_callbacks_run(
         if (r < 0)
                 return r;
 
-        if (!streq(c->vtable->method.signature, signature)) {
+        if (!streq(strempty(c->vtable->method.signature), signature)) {
                 r = sd_bus_reply_method_errorf(bus, m,
                                                "org.freedesktop.DBus.Error.InvalidArgs",
                                                "Invalid arguments '%s' to call %s:%s, expecting '%s'.",
-                                               signature, c->interface, c->member, c->vtable->method.signature);
+                                               signature, c->interface, c->member, strempty(c->vtable->method.signature));
                 if (r < 0)
                         return r;
 
@@ -2132,6 +2132,8 @@ static int invoke_property_get(
 
         /* Automatic handling if no callback is defined. */
 
+        assert(bus_type_is_basic(v->property.signature[0]));
+
         switch (v->property.signature[0]) {
 
         case SD_BUS_TYPE_STRING:
@@ -2142,6 +2144,7 @@ static int invoke_property_get(
 
         default:
                 p = userdata;
+                break;
         }
 
         r = sd_bus_message_append_basic(m, v->property.signature[0], p);
@@ -2151,6 +2154,62 @@ static int invoke_property_get(
         return 1;
 }
 
+static int invoke_property_set(
+                sd_bus *bus,
+                const sd_bus_vtable *v,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *value,
+                sd_bus_error *error,
+                void *userdata) {
+
+        int r;
+
+        assert(bus);
+        assert(v);
+
+        if (v->property.set)
+                return v->property.set(bus, path, interface, property, value, error, userdata);
+
+        /*  Automatic handling if no callback is defined. */
+
+        assert(signature_is_single(v->property.signature, false));
+        assert(bus_type_is_basic(v->property.signature[0]));
+
+        switch (v->property.signature[0]) {
+
+        case SD_BUS_TYPE_STRING:
+        case SD_BUS_TYPE_OBJECT_PATH:
+        case SD_BUS_TYPE_SIGNATURE: {
+                const char *p;
+                char *n;
+
+                r = sd_bus_message_read_basic(value, v->property.signature[0], &p);
+                if (r < 0)
+                        return r;
+
+                n = strdup(p);
+                if (!n)
+                        return -ENOMEM;
+
+                free(*(char**) userdata);
+                *(char**) userdata = n;
+
+                break;
+        }
+
+        default:
+                r = sd_bus_message_read_basic(value, v->property.signature[0], userdata);
+                if (r < 0)
+                        return r;
+
+                break;
+        }
+
+        return 1;
+}
+
 static int property_get_set_callbacks_run(
                 sd_bus *bus,
                 sd_bus_message *m,
@@ -2212,12 +2271,9 @@ static int property_get_set_callbacks_run(
                         if (r < 0)
                                 return r;
 
-                        if (c->vtable->property.set) {
-                                r = c->vtable->property.set(bus, m->path, c->interface, c->member, m, &error, u);
-                                if (r < 0)
-                                        return r;
-                        } else
-                                assert_not_reached("automatic properties not supported yet");
+                        r = invoke_property_set(bus, c->vtable, m->path, c->interface, c->member, m, &error, u);
+                        if (r < 0)
+                                return r;
                 }
 
                 if (sd_bus_error_is_set(&error)) {
@@ -3767,8 +3823,8 @@ static int add_object_vtable_internal(
                         struct vtable_member *m;
 
                         if (!member_name_is_valid(v->method.member) ||
-                            !signature_is_valid(v->method.signature, false) ||
-                            !signature_is_valid(v->method.result, false) ||
+                            !signature_is_valid(strempty(v->method.signature), false) ||
+                            !signature_is_valid(strempty(v->method.result), false) ||
                             !(v->method.handler || (isempty(v->method.signature) && isempty(v->method.result))) ||
                             v->flags & (SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE|SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY)) {
                                 r = -EINVAL;
@@ -3796,8 +3852,16 @@ static int add_object_vtable_internal(
                         break;
                 }
 
-                case _SD_BUS_VTABLE_PROPERTY:
-                case _SD_BUS_VTABLE_WRITABLE_PROPERTY: {
+                case _SD_BUS_VTABLE_WRITABLE_PROPERTY:
+
+                        if (!(v->property.set || bus_type_is_basic(v->property.signature[0]))) {
+                                r = -EINVAL;
+                                goto fail;
+                        }
+
+                        /* Fall through */
+
+                case _SD_BUS_VTABLE_PROPERTY: {
                         struct vtable_member *m;
 
                         if (!member_name_is_valid(v->property.member) ||
@@ -3834,7 +3898,7 @@ static int add_object_vtable_internal(
                 case _SD_BUS_VTABLE_SIGNAL:
 
                         if (!member_name_is_valid(v->signal.member) ||
-                            !signature_is_single(v->signal.signature, false)) {
+                            !signature_is_single(strempty(v->signal.signature), false)) {
                                 r = -EINVAL;
                                 goto fail;
                         }
index 637e051..1c23c21 100644 (file)
@@ -38,7 +38,6 @@
  *
  *   Add in:
  *
- *   automatic properties for Set()
  *   node hierarchy updates during dispatching
  *   emit_interfaces_added/emit_interfaces_removed
  *
@@ -48,7 +47,7 @@ struct context {
         int fds[2];
         bool quit;
         char *something;
-        const char *automatic_string_property;
+        char *automatic_string_property;
         uint32_t automatic_integer_property;
 };
 
@@ -153,8 +152,8 @@ static const sd_bus_vtable vtable[] = {
         SD_BUS_METHOD("AlterSomething", "s", "s", something_handler, 0),
         SD_BUS_METHOD("Exit", "", "", exit_handler, 0),
         SD_BUS_WRITABLE_PROPERTY("Something", "s", get_handler, set_handler, 0, 0),
-        SD_BUS_PROPERTY("AutomaticStringProperty", "s", NULL, offsetof(struct context, automatic_string_property), 0),
-        SD_BUS_PROPERTY("AutomaticIntegerProperty", "u", NULL, offsetof(struct context, automatic_integer_property), 0),
+        SD_BUS_WRITABLE_PROPERTY("AutomaticStringProperty", "s", NULL, NULL, offsetof(struct context, automatic_string_property), 0),
+        SD_BUS_WRITABLE_PROPERTY("AutomaticIntegerProperty", "u", NULL, NULL, offsetof(struct context, automatic_integer_property), 0),
         SD_BUS_METHOD("NoOperation", "", "", NULL, 0),
         SD_BUS_VTABLE_END
 };
@@ -288,6 +287,16 @@ static int client(struct context *c) {
         sd_bus_message_unref(reply);
         reply = NULL;
 
+        r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AutomaticIntegerProperty", &error, "u", 815);
+        assert_se(r >= 0);
+
+        assert_se(c->automatic_integer_property == 815);
+
+        r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AutomaticStringProperty", &error, "s", "Du Dödel, Du!");
+        assert_se(r >= 0);
+
+        assert_se(streq(c->automatic_string_property, "Du Dödel, Du!"));
+
         r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
         assert_se(r >= 0);
 
@@ -393,7 +402,7 @@ int main(int argc, char *argv[]) {
         zero(c);
 
         c.automatic_integer_property = 4711;
-        c.automatic_string_property = "dudeldu";
+        assert_se(c.automatic_string_property = strdup("dudeldu"));
 
         assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, c.fds) >= 0);
 
@@ -414,6 +423,7 @@ int main(int argc, char *argv[]) {
                 return PTR_TO_INT(p);
 
         free(c.something);
+        free(c.automatic_string_property);
 
         return EXIT_SUCCESS;
 }
index 9268247..2c12cf0 100644 (file)
@@ -57,12 +57,9 @@ typedef struct {
 /* Callbacks */
 
 typedef int (*sd_bus_message_handler_t)(sd_bus *bus, sd_bus_message *m, void *userdata);
-
 typedef int (*sd_bus_property_get_t) (sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, sd_bus_error *error, void *userdata);
 typedef int (*sd_bus_property_set_t) (sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, sd_bus_error *error, void *userdata);
-
 typedef int (*sd_bus_object_find_t) (sd_bus *bus, const char *path, const char *interface, void **found, void *userdata);
-
 typedef int (*sd_bus_node_enumerator_t) (sd_bus *bus, const char *path, char ***nodes, void *userdata);
 
 #include "sd-bus-protocol.h"