[SSSD] [PATCH] Implement org.freedesktop.DBus.Properties.GetAll for primitive types

Jakub Hrozek jhrozek at redhat.com
Wed May 21 20:53:16 UTC 2014


Hi,

the attached patches implement the
org.freedesktop.DBus.Properties.GetAll method for retrieving primitive
types and their arrays.

The patchset build on the previous set (currently still on review) that
implements the .Get method. The GetAll handler simply walks through the
existing getters and retrieves the results, storing them in a single
variant.

The patches include a unit test that tests all currently supported
combinations of primitive types and array of primitive types.
-------------- next part --------------
>From fc4b278c0914b2c7001393e471f4f6f0b532ba54 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Wed, 21 May 2014 16:48:45 +0200
Subject: [PATCH 1/5] SBUS: Add utility function sbus_add_variant_to_dict

---
 src/sbus/sssd_dbus.h            |   5 ++
 src/sbus/sssd_dbus_properties.c | 116 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 121 insertions(+)

diff --git a/src/sbus/sssd_dbus.h b/src/sbus/sssd_dbus.h
index 4ae64f054cdcf0e4005d99d907b878abb85c7137..9bd5019ecbd393eaef83b95c9e5fec5480b947af 100644
--- a/src/sbus/sssd_dbus.h
+++ b/src/sbus/sssd_dbus.h
@@ -269,6 +269,11 @@ int sbus_request_return_and_finish(struct sbus_request *dbus_req,
                                    int first_arg_type,
                                    ...);
 
+int sbus_add_variant_to_dict(DBusMessageIter *iter_dict,
+                             const char *key,
+                             int type,
+                             const void *value);
+
 int sbus_request_return_as_variant(struct sbus_request *dbus_req,
                                    int type,
                                    const void *value);
diff --git a/src/sbus/sssd_dbus_properties.c b/src/sbus/sssd_dbus_properties.c
index bdd5b432fe57ca66a4d06f98720578b3a175a65c..07b33297b13782354cbcf812f129443a14c5d319 100644
--- a/src/sbus/sssd_dbus_properties.c
+++ b/src/sbus/sssd_dbus_properties.c
@@ -23,6 +23,74 @@
 #include "sbus/sssd_dbus_meta.h"
 #include "sbus/sssd_dbus_private.h"
 
+static char *
+type_to_string(char type, char *str)
+{
+    int l;
+
+    l = snprintf(str, 2, "%c", type);
+    if (l != 1) {
+        return NULL;
+    }
+
+    return str;
+}
+
+int sbus_add_variant_to_dict(DBusMessageIter *iter_dict,
+                             const char *key,
+                             int type,
+                             const void *value)
+{
+    DBusMessageIter iter_dict_entry;
+    DBusMessageIter iter_dict_val;
+    dbus_bool_t dbret;
+    char strtype[2];
+
+    type_to_string(type, strtype);
+
+    dbret = dbus_message_iter_open_container(iter_dict,
+                                             DBUS_TYPE_DICT_ENTRY, NULL,
+                                             &iter_dict_entry);
+    if (!dbret) {
+        return ENOMEM;
+    }
+
+    /* Start by appending the key */
+    dbret = dbus_message_iter_append_basic(&iter_dict_entry,
+                                           DBUS_TYPE_STRING, &key);
+    if (!dbret) {
+        return ENOMEM;
+    }
+
+    dbret = dbus_message_iter_open_container(&iter_dict_entry,
+                                             DBUS_TYPE_VARIANT,
+                                             strtype,
+                                             &iter_dict_val);
+    if (!dbret) {
+        return ENOMEM;
+    }
+
+    /* Now add the value */
+    dbret = dbus_message_iter_append_basic(&iter_dict_val, type, value);
+    if (!dbret) {
+        return ENOMEM;
+    }
+
+    dbret = dbus_message_iter_close_container(&iter_dict_entry,
+                                              &iter_dict_val);
+    if (!dbret) {
+        return ENOMEM;
+    }
+
+    dbret = dbus_message_iter_close_container(iter_dict,
+                                              &iter_dict_entry);
+    if (!dbret) {
+        return ENOMEM;
+    }
+
+    return EOK;
+}
+
 static int
 dispatch_properties_set(struct sbus_connection *conn,
                         struct sbus_interface *intf,
@@ -176,6 +244,50 @@ dispatch_properties_get(struct sbus_connection *conn,
     return EOK;
 }
 
+static int
+dispatch_properties_get_all(struct sbus_connection *conn,
+                            struct sbus_interface *intf,
+                            DBusMessage *message)
+{
+    struct sbus_request *req;
+    const char *signature;
+    const struct sbus_interface_meta *meta;
+    const char *interface_name;
+    DBusMessageIter iter;
+
+    req = sbus_new_request(conn, intf, message);
+    if (req == NULL) {
+        return ENOMEM;
+    }
+
+    meta = intf->vtable->meta;
+
+    signature = dbus_message_get_signature(message);
+    /* Interface name */
+    if (strcmp(signature, "s") != 0) {
+        return sbus_request_fail_and_finish(req,
+                    sbus_error_new(req,
+                                   DBUS_ERROR_INVALID_ARGS,
+                                   "Invalid argument types passed " \
+                                   "to Set method"));
+    }
+
+    dbus_message_iter_init(message, &iter);
+    dbus_message_iter_get_basic(&iter, &interface_name);
+
+    if (strcmp(interface_name, meta->name) != 0) {
+        return sbus_request_fail_and_finish(req,
+                    sbus_error_new(req,
+                                   DBUS_ERROR_UNKNOWN_INTERFACE,
+                                   "No such interface"));
+    }
+
+    sbus_request_invoke_or_finish(req, NULL,
+                                  intf->instance_data,
+                                  meta->invoker_get_all);
+    return EOK;
+}
+
 int sbus_properties_dispatch(struct sbus_request *dbus_req)
 {
     const char *member;
@@ -191,6 +303,10 @@ int sbus_properties_dispatch(struct sbus_request *dbus_req)
         return dispatch_properties_get(dbus_req->conn,
                                        dbus_req->intf,
                                        dbus_req->message);
+    } else if (strcmp (member, "GetAll") == 0) {
+        return dispatch_properties_get_all(dbus_req->conn,
+                                            dbus_req->intf,
+                                            dbus_req->message);
     }
 
     return ERR_SBUS_NOSUP;
-- 
1.9.0

-------------- next part --------------
>From 5430119734058c44b62f222b016c91e250ec1ee0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina at redhat.com>
Date: Wed, 21 May 2014 16:41:13 +0200
Subject: [PATCH 2/5] SBUS: Add utility function
 sbus_add_array_as_variant_to_dict

---
 src/sbus/sssd_dbus.h            |  7 ++++
 src/sbus/sssd_dbus_properties.c | 76 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 83 insertions(+)

diff --git a/src/sbus/sssd_dbus.h b/src/sbus/sssd_dbus.h
index 9bd5019ecbd393eaef83b95c9e5fec5480b947af..0b7c7f1051f7a35734f4e39e70eed9e4e768471e 100644
--- a/src/sbus/sssd_dbus.h
+++ b/src/sbus/sssd_dbus.h
@@ -274,6 +274,13 @@ int sbus_add_variant_to_dict(DBusMessageIter *iter_dict,
                              int type,
                              const void *value);
 
+int sbus_add_array_as_variant_to_dict(DBusMessageIter *iter_dict,
+                                      const char *key,
+                                      int type,
+                                      uint8_t *values,
+                                      const int len,
+                                      const unsigned int item_size);
+
 int sbus_request_return_as_variant(struct sbus_request *dbus_req,
                                    int type,
                                    const void *value);
diff --git a/src/sbus/sssd_dbus_properties.c b/src/sbus/sssd_dbus_properties.c
index 07b33297b13782354cbcf812f129443a14c5d319..a85f0d6e2e5ec40c50a960e0266d97326e1096a1 100644
--- a/src/sbus/sssd_dbus_properties.c
+++ b/src/sbus/sssd_dbus_properties.c
@@ -91,6 +91,82 @@ int sbus_add_variant_to_dict(DBusMessageIter *iter_dict,
     return EOK;
 }
 
+int sbus_add_array_as_variant_to_dict(DBusMessageIter *iter_dict,
+                                      const char *key,
+                                      int type,
+                                      uint8_t *values,
+                                      const int len,
+                                      const unsigned int item_size)
+{
+    DBusMessageIter iter_dict_entry;
+    DBusMessageIter iter_variant;
+    DBusMessageIter iter_array;
+    dbus_bool_t dbret;
+    char variant_type[] = {DBUS_TYPE_ARRAY, type, '\0'};
+    char array_type[] = {type, '\0'};
+    void *addr = NULL;
+    int i;
+
+    dbret = dbus_message_iter_open_container(iter_dict,
+                                             DBUS_TYPE_DICT_ENTRY, NULL,
+                                             &iter_dict_entry);
+    if (!dbret) {
+        return ENOMEM;
+    }
+
+    /* Start by appending the key */
+    dbret = dbus_message_iter_append_basic(&iter_dict_entry,
+                                           DBUS_TYPE_STRING, &key);
+    if (!dbret) {
+        return ENOMEM;
+    }
+
+    dbret = dbus_message_iter_open_container(&iter_dict_entry,
+                                             DBUS_TYPE_VARIANT,
+                                             variant_type,
+                                             &iter_variant);
+    if (!dbret) {
+        return ENOMEM;
+    }
+
+    dbret = dbus_message_iter_open_container(&iter_variant,
+                                             DBUS_TYPE_ARRAY,
+                                             array_type,
+                                             &iter_array);
+    if (!dbret) {
+        return ENOMEM;
+    }
+
+    /* Now add the value */
+    for (i = 0; i < len; i++) {
+        addr = values + i * item_size;
+        dbret = dbus_message_iter_append_basic(&iter_array, type, addr);
+        if (!dbret) {
+            return ENOMEM;
+        }
+    }
+
+    dbret = dbus_message_iter_close_container(&iter_variant,
+                                              &iter_array);
+    if (!dbret) {
+        return ENOMEM;
+    }
+
+    dbret = dbus_message_iter_close_container(&iter_dict_entry,
+                                              &iter_variant);
+    if (!dbret) {
+        return ENOMEM;
+    }
+
+    dbret = dbus_message_iter_close_container(iter_dict,
+                                              &iter_dict_entry);
+    if (!dbret) {
+        return ENOMEM;
+    }
+
+    return EOK;
+}
+
 static int
 dispatch_properties_set(struct sbus_connection *conn,
                         struct sbus_interface *intf,
-- 
1.9.0

-------------- next part --------------
>From 0bc659d2ef1ad5ef7e0a821ffd35904807c377c7 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Wed, 21 May 2014 21:24:42 +0200
Subject: [PATCH 3/5] SBUS: Consolidate VTABLE_FUNC definitions in
 sssd_dbus_meta.h

We had several duplicated declarations of the VTABLE_FUNC macro in the
SSSD source code. This patch consolidates on one definition in
sssd_dbus_meta.h that is usable by all consumers, including the upcoming
GetAll method implementation.
---
 src/sbus/sssd_dbus_connection.c | 4 ----
 src/sbus/sssd_dbus_meta.h       | 4 ++++
 src/sbus/sssd_dbus_private.h    | 4 ----
 3 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/src/sbus/sssd_dbus_connection.c b/src/sbus/sssd_dbus_connection.c
index af1c8c56afee7a033e90bc6b2e92c7d8258139a0..06256a85b5e81b39d50923db6d41b64015114ce1 100644
--- a/src/sbus/sssd_dbus_connection.c
+++ b/src/sbus/sssd_dbus_connection.c
@@ -394,10 +394,6 @@ static bool sbus_iface_handles_path(struct sbus_interface_p *intf_p,
     return strcmp(path, intf_p->intf->path) == 0;
 }
 
-/* Looks up a vtable func, in a struct derived from struct sbus_vtable */
-#define VTABLE_FUNC(vtable, offset) \
-    (*((void **)((char *)(vtable) + (offset))))
-
 static void sbus_handler_got_caller_id(struct tevent_req *req);
 
 /* messsage_handler
diff --git a/src/sbus/sssd_dbus_meta.h b/src/sbus/sssd_dbus_meta.h
index 4e170b7d6ce5fb8f68109e496ab96cfdf889d864..f25b1ac28abf1b1ef53fa54a090fa84ef868ab77 100644
--- a/src/sbus/sssd_dbus_meta.h
+++ b/src/sbus/sssd_dbus_meta.h
@@ -33,6 +33,10 @@
  * http://dbus.freedesktop.org/doc/dbus-specification.html#introspection-format
  */
 
+/* Looks up a vtable func, in a struct derived from struct sbus_vtable */
+#define VTABLE_FUNC(vtable, offset) \
+    (*((void **)((char *)(vtable) + (offset))))
+
 struct sbus_arg_meta {
     const char *name;
     const char *type;
diff --git a/src/sbus/sssd_dbus_private.h b/src/sbus/sssd_dbus_private.h
index fa11bc1c8ef625ba6c6e9382d7ccd146eabdbb26..624448d30526eb4e927f22f133451c9a63c2cebd 100644
--- a/src/sbus/sssd_dbus_private.h
+++ b/src/sbus/sssd_dbus_private.h
@@ -68,10 +68,6 @@ struct sbus_connection {
     struct sbus_watch_ctx *watch_list;
 };
 
-/* Looks up a vtable func, in a struct derived from struct sbus_vtable */
-#define VTABLE_FUNC(vtable, offset) \
-    (*((void **)((char *)(vtable) + (offset))))
-
 /* =Watches=============================================================== */
 
 struct sbus_watch_ctx {
-- 
1.9.0

-------------- next part --------------
>From ad74733df63463710f48590f4d81bf1dd56f76ef Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Wed, 21 May 2014 21:29:15 +0200
Subject: [PATCH 4/5] SBUS: Implement org.freedesktop.DBus.Properties.GetAll
 for primitive types

This patch implements the GetAll method of the
org.freedesktop.DBus.Properties interface by iterating over the
available getters and putting all the results into a single getter.

The patch includes a unit test that exercies all currently supported
array types.
---
 src/monitor/monitor_iface_generated.c         |   2 +
 src/providers/data_provider_iface_generated.c |   2 +
 src/responder/ifp/ifp_iface_generated.c       |   1 +
 src/sbus/sbus_codegen                         |  96 +++++-
 src/sbus/sssd_dbus_meta.h                     |   1 +
 src/tests/sbus_codegen_tests.c                | 299 +++++++++++++++++++
 src/tests/sbus_codegen_tests_generated.c      | 415 +++++++++++++++++++++++++-
 7 files changed, 806 insertions(+), 10 deletions(-)

diff --git a/src/monitor/monitor_iface_generated.c b/src/monitor/monitor_iface_generated.c
index e9c3c1d52468ac6969498e79491a1d62dc75cc71..4e63eec5ef5a8f38fec454c39eeb42af99624035 100644
--- a/src/monitor/monitor_iface_generated.c
+++ b/src/monitor/monitor_iface_generated.c
@@ -30,6 +30,7 @@ const struct sbus_interface_meta mon_srv_iface_meta = {
     mon_srv_iface__methods,
     NULL, /* no signals */
     NULL, /* no propetries */
+    NULL, /* no GetAll invoker */
 };
 
 /* methods for org.freedesktop.sssd.service */
@@ -99,4 +100,5 @@ const struct sbus_interface_meta mon_cli_iface_meta = {
     mon_cli_iface__methods,
     NULL, /* no signals */
     NULL, /* no propetries */
+    NULL, /* no GetAll invoker */
 };
diff --git a/src/providers/data_provider_iface_generated.c b/src/providers/data_provider_iface_generated.c
index e7eca7def576772a695457444de7aaf99795fb65..faf2799972e09609b62543ac961e7b78d87ea557 100644
--- a/src/providers/data_provider_iface_generated.c
+++ b/src/providers/data_provider_iface_generated.c
@@ -65,6 +65,7 @@ const struct sbus_interface_meta data_provider_iface_meta = {
     data_provider_iface__methods,
     NULL, /* no signals */
     NULL, /* no propetries */
+    NULL, /* no GetAll invoker */
 };
 
 /* methods for org.freedesktop.sssd.dataprovider_rev */
@@ -92,4 +93,5 @@ const struct sbus_interface_meta data_provider_rev_iface_meta = {
     data_provider_rev_iface__methods,
     NULL, /* no signals */
     NULL, /* no propetries */
+    NULL, /* no GetAll invoker */
 };
diff --git a/src/responder/ifp/ifp_iface_generated.c b/src/responder/ifp/ifp_iface_generated.c
index d3cb4990cf13fd51621b7606371cdf3175bc789a..0788787ce8b693209c635e995bff70ac77e8640c 100644
--- a/src/responder/ifp/ifp_iface_generated.c
+++ b/src/responder/ifp/ifp_iface_generated.c
@@ -72,6 +72,7 @@ const struct sbus_interface_meta infopipe_iface_meta = {
     infopipe_iface__methods,
     NULL, /* no signals */
     NULL, /* no propetries */
+    NULL, /* no GetAll invoker */
 };
 
 /* invokes a handler with a 's' DBus signature */
diff --git a/src/sbus/sbus_codegen b/src/sbus/sbus_codegen
index 6507753f2797b354da8aaa2503b7d9bd701668c8..1650439750a8528d6cf4e0d222ef054706be33e0 100755
--- a/src/sbus/sbus_codegen
+++ b/src/sbus/sbus_codegen
@@ -291,6 +291,21 @@ def source_method_invoker(signature, args):
     out(");")
     out("}")
 
+def source_prop_types(prop, type_prefix=False):
+    prefix = "%s_" % prop.type if type_prefix else ""
+    if prop.is_array:
+        out("    %s *%sprop_val;", prop.sssd_type, prefix)
+        out("    int %sprop_len;", prefix)
+        out("    %s *%sout_val;", prop.dbus_type, prefix)
+    else:
+        out("    %s %sprop_val;", prop.sssd_type, prefix)
+        out("    %s %sout_val;", prop.dbus_type, prefix)
+
+def source_prop_handler(prop, type_prefix=False):
+    prefix = "%s_" % prop.type if type_prefix else ""
+    out("    %s", prop.getter_signature("%shandler" % prefix), new_line=False)
+    out(";")
+
 def source_getter_invoker(prop):
     out("")
     if prop.is_array:
@@ -300,13 +315,9 @@ def source_getter_invoker(prop):
     out("static int %s(struct sbus_request *dbus_req, void *function_ptr)",
         prop.getter_invoker_name())
     out("{")
-    if prop.is_array:
-        out("    %s *prop_val;", prop.sssd_type)
-        out("    int prop_len;")
-        out("    %s *out_val;", prop.dbus_type)
-    else:
-        out("    %s prop_val;", prop.sssd_type)
-        out("    %s out_val;", prop.dbus_type)
+
+    source_prop_types(prop)
+
     out("")
     out("    %s", prop.getter_signature("handler"), new_line=False)
     out(" = function_ptr;")
@@ -330,6 +341,72 @@ def source_getter_invoker(prop):
         out("    return sbus_request_return_as_variant(dbus_req, %s, &out_val);", prop.dbus_constant)
     out("}")
 
+def source_getall_invoker(iface, prop_invokers):
+    out("")
+    out("/* invokes GetAll for the '%s' interface */", iface.name)
+    out("static int invoke_%s_get_all(struct sbus_request *dbus_req, void *function_ptr)",
+        iface.c_name())
+    out("{")
+    out("    struct sbus_interface *intf = dbus_req->intf;")
+    out("    const struct sbus_property_meta *property;")
+    out("    DBusMessage *reply;")
+    out("    dbus_bool_t dbret;")
+    out("    DBusMessageIter iter;")
+    out("    DBusMessageIter iter_dict;")
+    out("    int ret;")
+
+    iface_types = [ p.type for p in iface.properties ]
+    for prop in [ p for p in prop_invokers.values() if p.type in iface_types ]:
+        source_prop_types(prop, type_prefix=True)
+        source_prop_handler(prop, type_prefix=True)
+    out("")
+
+    out("    reply = dbus_message_new_method_return(dbus_req->message);")
+    out("    if (!reply) return ENOMEM;")
+    out("    dbus_message_iter_init_append(reply, &iter);")
+    out("    dbret = dbus_message_iter_open_container(")
+    out("                                     &iter, DBUS_TYPE_ARRAY,")
+    out("                                     DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING")
+    out("                                     DBUS_TYPE_STRING_AS_STRING")
+    out("                                     DBUS_TYPE_VARIANT_AS_STRING")
+    out("                                     DBUS_DICT_ENTRY_END_CHAR_AS_STRING,")
+    out("                                     &iter_dict);")
+    out("    if (!dbret) return ENOMEM;")
+    out("")
+
+    for prop in iface.properties:
+        out("    property = sbus_meta_find_property(intf->vtable->meta, \"%s\");", prop.c_name())
+        out("    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {")
+        out("        %s_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);", prop.type)
+        out("        if (%s_handler) {", prop.type)
+        out("            (%s_handler)(dbus_req, dbus_req->intf->instance_data, &%s_prop_val", prop.type, prop.type, new_line=False)
+        if prop.is_array:
+            out(", &%s_prop_len", prop.type, new_line=False)
+        out(");")
+        if prop.type == "s":
+            out("            %s_out_val = %s_prop_val == NULL ? \"\" : %s_prop_val;",
+                prop.type, prop.type, prop.type)
+        elif prop.type == "o":
+            out("            %s_out_val = %s_prop_val == NULL ? \"/\" : %s_prop_val;",
+                prop.type, prop.type, prop.type)
+        else:
+            out("            %s_out_val = %s_prop_val;", prop.type, prop.type)
+        if prop.is_array:
+            out("            ret = sbus_add_array_as_variant_to_dict(&iter_dict, \"%s\", %s, (uint8_t*)%s_out_val, %s_prop_len, sizeof(%s));", prop.c_name(), prop.dbus_constant, prop.type, prop.type, prop.sssd_type)
+        else:
+            out("            ret = sbus_add_variant_to_dict(&iter_dict, \"%s\", %s, &%s_out_val);", prop.c_name(), prop.dbus_constant, prop.type)
+        out("            if (ret != EOK) return ret;")
+        out("        }")
+        out("    }")
+        out("")
+
+    out("    dbret = dbus_message_iter_close_container(&iter, &iter_dict);")
+    out("    if (!dbret) return ENOMEM;")
+    out("")
+
+    out("    return sbus_request_finish(dbus_req, reply);")
+    out("}")
+
 def forward_method_invokers(ifaces):
     invokers = { }
     for iface in ifaces:
@@ -509,9 +586,11 @@ def source_interface(iface):
     else:
         out("    NULL, /* no signals */")
     if iface.properties:
-        out("    %s__properties", iface.c_name())
+        out("    %s__properties,", iface.c_name())
+        out("    invoke_%s_get_all, /* GetAll invoker */", iface.c_name())
     else:
         out("    NULL, /* no propetries */")
+        out("    NULL, /* no GetAll invoker */")
     out("};")
 
 def generate_source(ifaces, filename, include_header=None):
@@ -541,6 +620,7 @@ def generate_source(ifaces, filename, include_header=None):
 
         # The properties array
         if iface.properties:
+            source_getall_invoker(iface, prop_invokers)
             source_properties(iface, iface.properties)
 
         # The sbus_interface structure
diff --git a/src/sbus/sssd_dbus_meta.h b/src/sbus/sssd_dbus_meta.h
index f25b1ac28abf1b1ef53fa54a090fa84ef868ab77..2cb9e95e3e12da55b1f101e076a0e05203984215 100644
--- a/src/sbus/sssd_dbus_meta.h
+++ b/src/sbus/sssd_dbus_meta.h
@@ -80,6 +80,7 @@ struct sbus_interface_meta {
     const struct sbus_method_meta *methods;
     const struct sbus_signal_meta *signals;
     const struct sbus_property_meta *properties;
+    sbus_method_invoker_fn invoker_get_all;
 };
 
 const struct sbus_method_meta *
diff --git a/src/tests/sbus_codegen_tests.c b/src/tests/sbus_codegen_tests.c
index c7da414fe30f46d9d317f3a4205ab38c4e905081..561a6a24809013437c6c5ea178359dc1248589b0 100644
--- a/src/tests/sbus_codegen_tests.c
+++ b/src/tests/sbus_codegen_tests.c
@@ -1033,12 +1033,311 @@ START_TEST(test_get_basic_array_types)
 }
 END_TEST
 
+struct prop_test {
+    const char *name;
+    bool handled;
+    int length;
+    int type;
+    union prop_value {
+        bool bool_val;
+        const char *string_val;
+        const char *path_val;
+        uint8_t byte_val;
+        int16_t int16_val;
+        uint16_t uint16_val;
+        int32_t int32_val;
+        uint32_t uint32_val;
+        int64_t int64_val;
+        uint64_t uint64_val;
+        double double_val;
+
+        const char **string_arr_val;
+        const char **path_arr_val;
+        uint8_t *byte_arr_val;
+        int16_t *int16_arr_val;
+        uint16_t *uint16_arr_val;
+        int32_t *int32_arr_val;
+        uint32_t *uint32_arr_val;
+        int64_t *int64_arr_val;
+        uint64_t *uint64_arr_val;
+        double *double_arr_val;
+    } value;
+};
+
+void check_prop(DBusMessageIter *variter, struct prop_test *p)
+{
+    dbus_bool_t bool_val;
+    const char *string_val;
+    const char *path_val;
+    uint8_t byte_val;
+    int16_t int16_val;
+    uint16_t uint16_val;
+    int32_t int32_val;
+    uint32_t uint32_val;
+    int64_t int64_val;
+    uint64_t uint64_val;
+    double double_val;
+    int type;
+
+    type = dbus_message_iter_get_arg_type(variter);
+
+    /* No property should be returned twice */
+    ck_assert(p->handled == false);
+    ck_assert(p->type == type);
+    switch (p->type) {
+        case DBUS_TYPE_BOOLEAN:
+            dbus_message_iter_get_basic(variter, &bool_val);
+            ck_assert(bool_val == p->value.bool_val);
+            break;
+        case DBUS_TYPE_STRING:
+            dbus_message_iter_get_basic(variter, &string_val);
+            ck_assert_str_eq(string_val, p->value.string_val);
+            break;
+        case DBUS_TYPE_BYTE:
+            dbus_message_iter_get_basic(variter, &byte_val);
+            ck_assert_int_eq(byte_val, p->value.byte_val);
+            break;
+        case DBUS_TYPE_INT16:
+            dbus_message_iter_get_basic(variter, &int16_val);
+            ck_assert_int_eq(int16_val, p->value.int16_val);
+            break;
+        case DBUS_TYPE_UINT16:
+            dbus_message_iter_get_basic(variter, &uint16_val);
+            ck_assert_int_eq(uint16_val, p->value.uint16_val);
+            break;
+        case DBUS_TYPE_INT32:
+            dbus_message_iter_get_basic(variter, &int32_val);
+            ck_assert_int_eq(int32_val, p->value.int32_val);
+            break;
+        case DBUS_TYPE_UINT32:
+            dbus_message_iter_get_basic(variter, &uint32_val);
+            ck_assert_int_eq(uint32_val, p->value.uint32_val);
+            break;
+        case DBUS_TYPE_INT64:
+            dbus_message_iter_get_basic(variter, &int64_val);
+            ck_assert_int_eq(int64_val, p->value.int64_val);
+            break;
+        case DBUS_TYPE_UINT64:
+            dbus_message_iter_get_basic(variter, &uint64_val);
+            ck_assert_int_eq(uint64_val, p->value.uint64_val);
+            break;
+        case DBUS_TYPE_DOUBLE:
+            dbus_message_iter_get_basic(variter, &double_val);
+            ck_assert_int_eq(double_val, p->value.double_val);
+            break;
+        case DBUS_TYPE_OBJECT_PATH:
+            dbus_message_iter_get_basic(variter, &path_val);
+            ck_assert_str_eq(path_val, p->value.path_val);
+            break;
+        default:
+            /* Not handled */
+            return;
+    }
+
+    /* This attribute was handled, get the next one */
+    p->handled = true;
+}
+
+void check_arr_prop(DBusMessageIter *variter, struct prop_test *p)
+{
+    DBusMessageIter arriter;
+    const char **strings;
+    uint8_t *byte_arr_val;
+    int16_t *int16_arr_val;
+    uint16_t *uint16_arr_val;
+    int32_t *int32_arr_val;
+    uint32_t *uint32_arr_val;
+    int64_t *int64_arr_val;
+    uint64_t *uint64_arr_val;
+    double *double_arr_val;
+    int len;
+    int type;
+
+    ck_assert_int_eq(dbus_message_iter_get_arg_type(variter), DBUS_TYPE_ARRAY);
+    type = dbus_message_iter_get_element_type(variter);
+    ck_assert_int_eq(type, p->type);
+
+    dbus_message_iter_recurse(variter, &arriter);
+    if (type == DBUS_TYPE_STRING || type == DBUS_TYPE_OBJECT_PATH) {
+        int n = 0, i = 0;;
+        const char *s;
+
+        do {
+            n++;
+        } while (dbus_message_iter_next(&arriter));
+
+        /* Allocating on NULL is bad, but this is unit test */
+        strings = talloc_array(NULL, const char *, n);
+        ck_assert(strings != NULL);
+
+        dbus_message_iter_recurse(variter, &arriter);
+        do {
+            dbus_message_iter_get_basic(&arriter, &s);
+            strings[i] = talloc_strdup(strings, s);
+            ck_assert(strings[i] != NULL);
+            i++;
+        } while (dbus_message_iter_next(&arriter));
+
+        len = n;
+    }
+
+    switch (p->type) {
+        case DBUS_TYPE_STRING:
+            ck_assert_int_eq(len, 2);
+            ck_assert_str_eq(strings[0], pilot_string_array[0]);
+            ck_assert_str_eq(strings[1], pilot_string_array[1]);
+            break;
+        case DBUS_TYPE_BYTE:
+            dbus_message_iter_get_fixed_array(&arriter, &byte_arr_val, &len);
+            check_uint_array(byte_arr_val, len, p->value.byte_arr_val);
+            break;
+        case DBUS_TYPE_INT16:
+            dbus_message_iter_get_fixed_array(&arriter, &int16_arr_val, &len);
+            check_int_array(int16_arr_val, len, p->value.int16_arr_val);
+            break;
+        case DBUS_TYPE_UINT16:
+            dbus_message_iter_get_fixed_array(&arriter, &uint16_arr_val, &len);
+            check_uint_array(uint16_arr_val, len, p->value.uint16_arr_val);
+            break;
+        case DBUS_TYPE_INT32:
+            dbus_message_iter_get_fixed_array(&arriter, &int32_arr_val, &len);
+            check_int_array(int32_arr_val, len, p->value.int32_arr_val);
+            break;
+        case DBUS_TYPE_UINT32:
+            dbus_message_iter_get_fixed_array(&arriter, &uint32_arr_val, &len);
+            check_uint_array(uint32_arr_val, len, p->value.uint32_arr_val);
+            break;
+        case DBUS_TYPE_INT64:
+            dbus_message_iter_get_fixed_array(&arriter, &int64_arr_val, &len);
+            check_int_array(int64_arr_val, len, p->value.int64_arr_val);
+            break;
+        case DBUS_TYPE_UINT64:
+            dbus_message_iter_get_fixed_array(&arriter, &uint64_arr_val, &len);
+            check_uint_array(uint64_arr_val, len, p->value.uint64_arr_val);
+            break;
+        case DBUS_TYPE_DOUBLE:
+            dbus_message_iter_get_fixed_array(&arriter, &double_arr_val, &len);
+            check_int_array(double_arr_val, len, p->value.double_arr_val);
+            break;
+        case DBUS_TYPE_OBJECT_PATH:
+            ck_assert_int_eq(len, 2);
+            ck_assert_str_eq(strings[0], pilot_path_array[0]);
+            ck_assert_str_eq(strings[1], pilot_path_array[1]);
+            break;
+        default:
+            /* Not handled */
+            return;
+    }
+
+
+    p->handled = true;
+}
+
+START_TEST(test_getall_basic_types)
+{
+    DBusMessage *reply;
+    DBusMessageIter iter;
+    DBusMessageIter arriter;
+    DBusMessageIter dictiter;
+    DBusMessageIter variter;
+    dbus_bool_t dbret;
+    DBusError error = DBUS_ERROR_INIT;
+    TALLOC_CTX *ctx;
+    DBusConnection *client;
+    char *attr_name;
+    int i;
+    int num_prop;
+
+    struct prop_test pilot_properties[] = {
+      { "boolean", false, 0, DBUS_TYPE_BOOLEAN, { .bool_val = pilot_bool } },
+      { "FullName", false, 0, DBUS_TYPE_STRING, { .string_val = pilot_full_name } },
+      { "byte", false, 0, DBUS_TYPE_BYTE, { .byte_val = pilot_byte } },
+      { "int16", false, 0, DBUS_TYPE_INT16, { .int16_val = pilot_int16 } },
+      { "uint16", false, 0, DBUS_TYPE_UINT16, { .uint16_val = pilot_uint16 } },
+      { "int32", false, 0, DBUS_TYPE_INT32, { .int32_val = pilot_int32 } },
+      { "uint32", false, 0, DBUS_TYPE_UINT32, { .uint32_val = pilot_uint32 } },
+      { "int64", false, 0, DBUS_TYPE_INT64, { .int64_val = pilot_int64 } },
+      { "uint64", false, 0, DBUS_TYPE_UINT64, { .uint64_val = pilot_uint64 } },
+      { "double", false, 0, DBUS_TYPE_DOUBLE, { .double_val = pilot_double } },
+      { "string", false, 0, DBUS_TYPE_STRING, { .string_val = pilot_string } },
+      { "object_path", false, 0, DBUS_TYPE_OBJECT_PATH, { .path_val = pilot_path } },
+      { "null_string", false, 0, DBUS_TYPE_STRING, { .string_val = "" } },
+      { "null_path", false, 0, DBUS_TYPE_OBJECT_PATH, { .path_val = "/" } },
+
+      { "byte_array", false, N_ELEMENTS(pilot_byte_array), DBUS_TYPE_BYTE, { .byte_arr_val = pilot_byte_array } },
+      { "int16_array", false, N_ELEMENTS(pilot_int16_array), DBUS_TYPE_INT16, { .int16_arr_val = pilot_int16_array } },
+      { "uint16_array", false, N_ELEMENTS(pilot_uint16_array), DBUS_TYPE_UINT16, { .uint16_arr_val = pilot_uint16_array } },
+      { "int32_array", false, N_ELEMENTS(pilot_int32_array), DBUS_TYPE_INT32, { .int32_arr_val = pilot_int32_array } },
+      { "uint32_array", false, N_ELEMENTS(pilot_uint32_array), DBUS_TYPE_UINT32, { .uint32_arr_val = pilot_uint32_array } },
+      { "int64_array", false, N_ELEMENTS(pilot_int64_array), DBUS_TYPE_INT64, { .int64_arr_val = pilot_int64_array } },
+      { "uint64_array", false, N_ELEMENTS(pilot_uint64_array), DBUS_TYPE_UINT64, { .uint64_arr_val = pilot_uint64_array } },
+      { "double_array", false, N_ELEMENTS(pilot_double_array), DBUS_TYPE_DOUBLE, { .double_arr_val = pilot_double_array } },
+      { "string_array", false, N_ELEMENTS(pilot_string_array), DBUS_TYPE_STRING, { .string_arr_val = pilot_string_array } },
+      { "object_path_array", false, N_ELEMENTS(pilot_path_array), DBUS_TYPE_OBJECT_PATH, { .path_arr_val = pilot_path_array } },
+
+      { NULL, false, 0, 0, { .bool_val = false } }};
+
+    ctx = talloc_new(NULL);
+    client = test_dbus_setup_mock(ctx, NULL, pilot_test_server_init, NULL);
+
+    reply = test_dbus_call_sync(client,
+                                "/test/leela",
+                                DBUS_PROPERTIES_INTERFACE,
+                                "GetAll",
+                                &error,
+                                DBUS_TYPE_STRING,
+                                &test_pilot_meta.name,
+                                DBUS_TYPE_INVALID);
+    ck_assert(reply != NULL);
+
+    /* GetAll reply is an array of dictionaries */
+    dbret = dbus_message_iter_init(reply, &iter);
+    ck_assert(dbret == TRUE);
+    ck_assert_int_eq(dbus_message_iter_get_arg_type(&iter), DBUS_TYPE_ARRAY);
+
+    dbus_message_iter_recurse(&iter, &arriter);
+    num_prop = 0;
+    do {
+        ck_assert_int_eq(dbus_message_iter_get_arg_type(&arriter),
+                         DBUS_TYPE_DICT_ENTRY);
+        dbus_message_iter_recurse(&arriter, &dictiter);
+        dbus_message_iter_get_basic(&dictiter, &attr_name);
+        ck_assert(dbus_message_iter_next(&dictiter) == TRUE);
+        ck_assert_int_eq(dbus_message_iter_get_arg_type(&dictiter),
+                         DBUS_TYPE_VARIANT);
+
+        dbus_message_iter_recurse(&dictiter, &variter);
+
+        for (i=0; pilot_properties[i].name; i++) {
+            if (strcmp(attr_name, pilot_properties[i].name) == 0) {
+                if (dbus_message_iter_get_arg_type(&variter) == DBUS_TYPE_ARRAY) {
+                    check_arr_prop(&variter, &pilot_properties[i]);
+                } else {
+                    check_prop(&variter, &pilot_properties[i]);
+                }
+                break;
+            }
+        }
+
+        num_prop++;
+    } while(dbus_message_iter_next(&arriter));
+
+    /* All known properties must be handled now */
+    for (i=0; pilot_properties[i].name; i++) {
+        ck_assert(pilot_properties[i].handled == true);
+    }
+    /* Also all properties returned from the bus must be accounted for */
+    ck_assert_uint_eq(num_prop, N_ELEMENTS(pilot_properties)-1);
+}
+END_TEST
+
 TCase *create_handler_tests(void)
 {
     TCase *tc = tcase_create("handler");
 
     tcase_add_test(tc, test_marshal_basic_types);
     tcase_add_test(tc, test_get_basic_types);
+    tcase_add_test(tc, test_getall_basic_types);
     tcase_add_test(tc, test_get_basic_array_types);
 
     return tc;
diff --git a/src/tests/sbus_codegen_tests_generated.c b/src/tests/sbus_codegen_tests_generated.c
index 70302daff7c7a7f5b042428be7d994fa0cdd660a..13a67f7be27b9347f5b005b1f3bb440ddc14b9d0 100644
--- a/src/tests/sbus_codegen_tests_generated.c
+++ b/src/tests/sbus_codegen_tests_generated.c
@@ -111,6 +111,49 @@ const struct sbus_signal_meta com_planetexpress_Ship__signals[] = {
     { NULL, }
 };
 
+/* invokes GetAll for the 'com.planetexpress.Ship' interface */
+static int invoke_com_planetexpress_Ship_get_all(struct sbus_request *dbus_req, void *function_ptr)
+{
+    struct sbus_interface *intf = dbus_req->intf;
+    const struct sbus_property_meta *property;
+    DBusMessage *reply;
+    dbus_bool_t dbret;
+    DBusMessageIter iter;
+    DBusMessageIter iter_dict;
+    int ret;
+    const char * s_prop_val;
+    const char * s_out_val;
+    void (*s_handler)(struct sbus_request *, void *data, const char * *);
+
+    reply = dbus_message_new_method_return(dbus_req->message);
+    if (!reply) return ENOMEM;
+    dbus_message_iter_init_append(reply, &iter);
+    dbret = dbus_message_iter_open_container(
+                                     &iter, DBUS_TYPE_ARRAY,
+                                     DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+                                     DBUS_TYPE_STRING_AS_STRING
+                                     DBUS_TYPE_VARIANT_AS_STRING
+                                     DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+                                     &iter_dict);
+    if (!dbret) return ENOMEM;
+
+    property = sbus_meta_find_property(intf->vtable->meta, "Color");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        s_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (s_handler) {
+            (s_handler)(dbus_req, dbus_req->intf->instance_data, &s_prop_val);
+            s_out_val = s_prop_val == NULL ? "" : s_prop_val;
+            ret = sbus_add_variant_to_dict(&iter_dict, "Color", DBUS_TYPE_STRING, &s_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    dbret = dbus_message_iter_close_container(&iter, &iter_dict);
+    if (!dbret) return ENOMEM;
+
+    return sbus_request_finish(dbus_req, reply);
+}
+
 /* property info for com.planetexpress.Ship */
 const struct sbus_property_meta com_planetexpress_Ship__properties[] = {
     {
@@ -130,7 +173,8 @@ const struct sbus_interface_meta com_planetexpress_Ship_meta = {
     "com.planetexpress.Ship", /* name */
     com_planetexpress_Ship__methods,
     com_planetexpress_Ship__signals,
-    com_planetexpress_Ship__properties
+    com_planetexpress_Ship__properties,
+    invoke_com_planetexpress_Ship_get_all, /* GetAll invoker */
 };
 
 /* arguments for com.planetexpress.Pilot.Blink */
@@ -252,6 +296,372 @@ const struct sbus_method_meta test_pilot__methods[] = {
     { NULL, }
 };
 
+/* invokes GetAll for the 'com.planetexpress.Pilot' interface */
+static int invoke_test_pilot_get_all(struct sbus_request *dbus_req, void *function_ptr)
+{
+    struct sbus_interface *intf = dbus_req->intf;
+    const struct sbus_property_meta *property;
+    DBusMessage *reply;
+    dbus_bool_t dbret;
+    DBusMessageIter iter;
+    DBusMessageIter iter_dict;
+    int ret;
+    uint16_t *aq_prop_val;
+    int aq_prop_len;
+    uint16_t *aq_out_val;
+    void (*aq_handler)(struct sbus_request *, void *data, uint16_t * *, int *);
+    bool b_prop_val;
+    dbus_bool_t b_out_val;
+    void (*b_handler)(struct sbus_request *, void *data, bool *);
+    double d_prop_val;
+    double d_out_val;
+    void (*d_handler)(struct sbus_request *, void *data, double *);
+    const char * *ao_prop_val;
+    int ao_prop_len;
+    const char * *ao_out_val;
+    void (*ao_handler)(struct sbus_request *, void *data, const char * * *, int *);
+    int32_t i_prop_val;
+    int32_t i_out_val;
+    void (*i_handler)(struct sbus_request *, void *data, int32_t *);
+    const char * *as_prop_val;
+    int as_prop_len;
+    const char * *as_out_val;
+    void (*as_handler)(struct sbus_request *, void *data, const char * * *, int *);
+    const char * o_prop_val;
+    const char * o_out_val;
+    void (*o_handler)(struct sbus_request *, void *data, const char * *);
+    int16_t n_prop_val;
+    int16_t n_out_val;
+    void (*n_handler)(struct sbus_request *, void *data, int16_t *);
+    uint16_t q_prop_val;
+    uint16_t q_out_val;
+    void (*q_handler)(struct sbus_request *, void *data, uint16_t *);
+    uint8_t *ay_prop_val;
+    int ay_prop_len;
+    uint8_t *ay_out_val;
+    void (*ay_handler)(struct sbus_request *, void *data, uint8_t * *, int *);
+    const char * s_prop_val;
+    const char * s_out_val;
+    void (*s_handler)(struct sbus_request *, void *data, const char * *);
+    uint32_t u_prop_val;
+    uint32_t u_out_val;
+    void (*u_handler)(struct sbus_request *, void *data, uint32_t *);
+    uint64_t t_prop_val;
+    uint64_t t_out_val;
+    void (*t_handler)(struct sbus_request *, void *data, uint64_t *);
+    int64_t *ax_prop_val;
+    int ax_prop_len;
+    int64_t *ax_out_val;
+    void (*ax_handler)(struct sbus_request *, void *data, int64_t * *, int *);
+    uint8_t y_prop_val;
+    uint8_t y_out_val;
+    void (*y_handler)(struct sbus_request *, void *data, uint8_t *);
+    int64_t x_prop_val;
+    int64_t x_out_val;
+    void (*x_handler)(struct sbus_request *, void *data, int64_t *);
+    uint32_t *au_prop_val;
+    int au_prop_len;
+    uint32_t *au_out_val;
+    void (*au_handler)(struct sbus_request *, void *data, uint32_t * *, int *);
+    int16_t *an_prop_val;
+    int an_prop_len;
+    int16_t *an_out_val;
+    void (*an_handler)(struct sbus_request *, void *data, int16_t * *, int *);
+    double *ad_prop_val;
+    int ad_prop_len;
+    double *ad_out_val;
+    void (*ad_handler)(struct sbus_request *, void *data, double * *, int *);
+    int32_t *ai_prop_val;
+    int ai_prop_len;
+    int32_t *ai_out_val;
+    void (*ai_handler)(struct sbus_request *, void *data, int32_t * *, int *);
+    uint64_t *at_prop_val;
+    int at_prop_len;
+    uint64_t *at_out_val;
+    void (*at_handler)(struct sbus_request *, void *data, uint64_t * *, int *);
+
+    reply = dbus_message_new_method_return(dbus_req->message);
+    if (!reply) return ENOMEM;
+    dbus_message_iter_init_append(reply, &iter);
+    dbret = dbus_message_iter_open_container(
+                                     &iter, DBUS_TYPE_ARRAY,
+                                     DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+                                     DBUS_TYPE_STRING_AS_STRING
+                                     DBUS_TYPE_VARIANT_AS_STRING
+                                     DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+                                     &iter_dict);
+    if (!dbret) return ENOMEM;
+
+    property = sbus_meta_find_property(intf->vtable->meta, "FullName");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        s_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (s_handler) {
+            (s_handler)(dbus_req, dbus_req->intf->instance_data, &s_prop_val);
+            s_out_val = s_prop_val == NULL ? "" : s_prop_val;
+            ret = sbus_add_variant_to_dict(&iter_dict, "FullName", DBUS_TYPE_STRING, &s_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "byte");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        y_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (y_handler) {
+            (y_handler)(dbus_req, dbus_req->intf->instance_data, &y_prop_val);
+            y_out_val = y_prop_val;
+            ret = sbus_add_variant_to_dict(&iter_dict, "byte", DBUS_TYPE_BYTE, &y_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "boolean");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        b_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (b_handler) {
+            (b_handler)(dbus_req, dbus_req->intf->instance_data, &b_prop_val);
+            b_out_val = b_prop_val;
+            ret = sbus_add_variant_to_dict(&iter_dict, "boolean", DBUS_TYPE_BOOLEAN, &b_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "int16");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        n_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (n_handler) {
+            (n_handler)(dbus_req, dbus_req->intf->instance_data, &n_prop_val);
+            n_out_val = n_prop_val;
+            ret = sbus_add_variant_to_dict(&iter_dict, "int16", DBUS_TYPE_INT16, &n_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "uint16");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        q_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (q_handler) {
+            (q_handler)(dbus_req, dbus_req->intf->instance_data, &q_prop_val);
+            q_out_val = q_prop_val;
+            ret = sbus_add_variant_to_dict(&iter_dict, "uint16", DBUS_TYPE_UINT16, &q_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "int32");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        i_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (i_handler) {
+            (i_handler)(dbus_req, dbus_req->intf->instance_data, &i_prop_val);
+            i_out_val = i_prop_val;
+            ret = sbus_add_variant_to_dict(&iter_dict, "int32", DBUS_TYPE_INT32, &i_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "uint32");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        u_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (u_handler) {
+            (u_handler)(dbus_req, dbus_req->intf->instance_data, &u_prop_val);
+            u_out_val = u_prop_val;
+            ret = sbus_add_variant_to_dict(&iter_dict, "uint32", DBUS_TYPE_UINT32, &u_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "int64");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        x_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (x_handler) {
+            (x_handler)(dbus_req, dbus_req->intf->instance_data, &x_prop_val);
+            x_out_val = x_prop_val;
+            ret = sbus_add_variant_to_dict(&iter_dict, "int64", DBUS_TYPE_INT64, &x_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "uint64");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        t_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (t_handler) {
+            (t_handler)(dbus_req, dbus_req->intf->instance_data, &t_prop_val);
+            t_out_val = t_prop_val;
+            ret = sbus_add_variant_to_dict(&iter_dict, "uint64", DBUS_TYPE_UINT64, &t_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "double");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        d_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (d_handler) {
+            (d_handler)(dbus_req, dbus_req->intf->instance_data, &d_prop_val);
+            d_out_val = d_prop_val;
+            ret = sbus_add_variant_to_dict(&iter_dict, "double", DBUS_TYPE_DOUBLE, &d_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "string");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        s_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (s_handler) {
+            (s_handler)(dbus_req, dbus_req->intf->instance_data, &s_prop_val);
+            s_out_val = s_prop_val == NULL ? "" : s_prop_val;
+            ret = sbus_add_variant_to_dict(&iter_dict, "string", DBUS_TYPE_STRING, &s_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "object_path");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        o_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (o_handler) {
+            (o_handler)(dbus_req, dbus_req->intf->instance_data, &o_prop_val);
+            o_out_val = o_prop_val == NULL ? "/" : o_prop_val;
+            ret = sbus_add_variant_to_dict(&iter_dict, "object_path", DBUS_TYPE_OBJECT_PATH, &o_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "null_string");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        s_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (s_handler) {
+            (s_handler)(dbus_req, dbus_req->intf->instance_data, &s_prop_val);
+            s_out_val = s_prop_val == NULL ? "" : s_prop_val;
+            ret = sbus_add_variant_to_dict(&iter_dict, "null_string", DBUS_TYPE_STRING, &s_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "null_path");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        o_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (o_handler) {
+            (o_handler)(dbus_req, dbus_req->intf->instance_data, &o_prop_val);
+            o_out_val = o_prop_val == NULL ? "/" : o_prop_val;
+            ret = sbus_add_variant_to_dict(&iter_dict, "null_path", DBUS_TYPE_OBJECT_PATH, &o_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "byte_array");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        ay_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (ay_handler) {
+            (ay_handler)(dbus_req, dbus_req->intf->instance_data, &ay_prop_val, &ay_prop_len);
+            ay_out_val = ay_prop_val;
+            ret = sbus_add_array_as_variant_to_dict(&iter_dict, "byte_array", DBUS_TYPE_BYTE, (uint8_t*)ay_out_val, ay_prop_len, sizeof(uint8_t));
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "int16_array");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        an_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (an_handler) {
+            (an_handler)(dbus_req, dbus_req->intf->instance_data, &an_prop_val, &an_prop_len);
+            an_out_val = an_prop_val;
+            ret = sbus_add_array_as_variant_to_dict(&iter_dict, "int16_array", DBUS_TYPE_INT16, (uint8_t*)an_out_val, an_prop_len, sizeof(int16_t));
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "uint16_array");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        aq_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (aq_handler) {
+            (aq_handler)(dbus_req, dbus_req->intf->instance_data, &aq_prop_val, &aq_prop_len);
+            aq_out_val = aq_prop_val;
+            ret = sbus_add_array_as_variant_to_dict(&iter_dict, "uint16_array", DBUS_TYPE_UINT16, (uint8_t*)aq_out_val, aq_prop_len, sizeof(uint16_t));
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "int32_array");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        ai_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (ai_handler) {
+            (ai_handler)(dbus_req, dbus_req->intf->instance_data, &ai_prop_val, &ai_prop_len);
+            ai_out_val = ai_prop_val;
+            ret = sbus_add_array_as_variant_to_dict(&iter_dict, "int32_array", DBUS_TYPE_INT32, (uint8_t*)ai_out_val, ai_prop_len, sizeof(int32_t));
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "uint32_array");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        au_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (au_handler) {
+            (au_handler)(dbus_req, dbus_req->intf->instance_data, &au_prop_val, &au_prop_len);
+            au_out_val = au_prop_val;
+            ret = sbus_add_array_as_variant_to_dict(&iter_dict, "uint32_array", DBUS_TYPE_UINT32, (uint8_t*)au_out_val, au_prop_len, sizeof(uint32_t));
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "int64_array");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        ax_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (ax_handler) {
+            (ax_handler)(dbus_req, dbus_req->intf->instance_data, &ax_prop_val, &ax_prop_len);
+            ax_out_val = ax_prop_val;
+            ret = sbus_add_array_as_variant_to_dict(&iter_dict, "int64_array", DBUS_TYPE_INT64, (uint8_t*)ax_out_val, ax_prop_len, sizeof(int64_t));
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "uint64_array");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        at_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (at_handler) {
+            (at_handler)(dbus_req, dbus_req->intf->instance_data, &at_prop_val, &at_prop_len);
+            at_out_val = at_prop_val;
+            ret = sbus_add_array_as_variant_to_dict(&iter_dict, "uint64_array", DBUS_TYPE_UINT64, (uint8_t*)at_out_val, at_prop_len, sizeof(uint64_t));
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "double_array");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        ad_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (ad_handler) {
+            (ad_handler)(dbus_req, dbus_req->intf->instance_data, &ad_prop_val, &ad_prop_len);
+            ad_out_val = ad_prop_val;
+            ret = sbus_add_array_as_variant_to_dict(&iter_dict, "double_array", DBUS_TYPE_DOUBLE, (uint8_t*)ad_out_val, ad_prop_len, sizeof(double));
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "string_array");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        as_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (as_handler) {
+            (as_handler)(dbus_req, dbus_req->intf->instance_data, &as_prop_val, &as_prop_len);
+            as_out_val = as_prop_val;
+            ret = sbus_add_array_as_variant_to_dict(&iter_dict, "string_array", DBUS_TYPE_STRING, (uint8_t*)as_out_val, as_prop_len, sizeof(const char *));
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "object_path_array");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        ao_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (ao_handler) {
+            (ao_handler)(dbus_req, dbus_req->intf->instance_data, &ao_prop_val, &ao_prop_len);
+            ao_out_val = ao_prop_val;
+            ret = sbus_add_array_as_variant_to_dict(&iter_dict, "object_path_array", DBUS_TYPE_OBJECT_PATH, (uint8_t*)ao_out_val, ao_prop_len, sizeof(const char *));
+            if (ret != EOK) return ret;
+        }
+    }
+
+    dbret = dbus_message_iter_close_container(&iter, &iter_dict);
+    if (!dbret) return ENOMEM;
+
+    return sbus_request_finish(dbus_req, reply);
+}
+
 /* property info for com.planetexpress.Pilot */
 const struct sbus_property_meta test_pilot__properties[] = {
     {
@@ -478,7 +888,8 @@ const struct sbus_interface_meta test_pilot_meta = {
     "com.planetexpress.Pilot", /* name */
     test_pilot__methods,
     NULL, /* no signals */
-    test_pilot__properties
+    test_pilot__properties,
+    invoke_test_pilot_get_all, /* GetAll invoker */
 };
 
 /* invokes a handler with a 'bu' DBus signature */
-- 
1.9.0

-------------- next part --------------
>From 32d84445012991dba38ee5b60f5614aca70b889d Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Wed, 21 May 2014 20:10:23 +0200
Subject: [PATCH 5/5] SBUS: Add org.freedesktop.DBus.Properties.GetAll to
 Introspection

---
 src/sbus/sssd_dbus_introspect.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/sbus/sssd_dbus_introspect.c b/src/sbus/sssd_dbus_introspect.c
index 4bd9563e6dad31009e92a0f4f7de97428a0185ca..cb8780dce3e08509dee6437fe57eae1dcc48ebe9 100644
--- a/src/sbus/sssd_dbus_introspect.c
+++ b/src/sbus/sssd_dbus_introspect.c
@@ -54,6 +54,10 @@ const struct sbus_method_meta introspect_method =
      "     <arg name=\"property\" direction=\"in\" type=\"s\"/>\n"          \
      "     <arg name=\"value\" direction=\"out\" type=\"v\"/>\n"            \
      "   </method>\n"                                                       \
+     "   <method name=\"GetAll\">\n"                                        \
+     "     <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n"         \
+     "     <arg name=\"properties\" direction=\"out\" type=\"a{sv}\"/>\n"   \
+     "   </method>\n"                                                       \
      " </interface>\n"
 
 struct introspect_ctx {
-- 
1.9.0



More information about the sssd-devel mailing list