summaryrefslogtreecommitdiffstats
path: root/src/sbus
diff options
context:
space:
mode:
authorJakub Hrozek <jhrozek@redhat.com>2014-04-23 03:01:21 +0200
committerJakub Hrozek <jhrozek@redhat.com>2014-05-22 17:36:20 +0200
commit90e04eae7e54ec892a6f239783df94dab5d1ed9a (patch)
tree78f6b1d72e26f079c8888238742614126ce67535 /src/sbus
parent1319e71fd1680ca4864afe0b1aca2b8c8e4a1ee4 (diff)
downloadsssd-90e04eae7e54ec892a6f239783df94dab5d1ed9a.tar.gz
sssd-90e04eae7e54ec892a6f239783df94dab5d1ed9a.tar.xz
sssd-90e04eae7e54ec892a6f239783df94dab5d1ed9a.zip
SBUS: Implement org.freedesktop.DBus.Properties.Get for primitive types
This patch implements type-safe getters for primitive types and their arrays. The patch includes unit tests of all supported types and arrays of these types. All getter are synchronous. The getters never fail, instead, they return a default or 'not defined' value. Making the getters synchronous and always returning a value will make it significantly easier to implement the GetAll method. Reviewed-by: Stef Walter <stefw@redhat.com> Reviewed-by: Pavel Březina <pbrezina@redhat.com>
Diffstat (limited to 'src/sbus')
-rwxr-xr-xsrc/sbus/sbus_codegen114
-rw-r--r--src/sbus/sssd_dbus_meta.h2
-rw-r--r--src/sbus/sssd_dbus_properties.c75
3 files changed, 151 insertions, 40 deletions
diff --git a/src/sbus/sbus_codegen b/src/sbus/sbus_codegen
index 96248a628..a8f91b784 100755
--- a/src/sbus/sbus_codegen
+++ b/src/sbus/sbus_codegen
@@ -187,6 +187,16 @@ class Property(Typed):
raise DBusXmlException('Invalid access type %s'%self.access)
def fq_c_name(self):
return "%s_%s" % (self.iface.c_name(), self.c_name())
+ def getter_name(self):
+ return "%s_get_%s" % (self.iface.c_name(), self.c_name())
+ def getter_invoker_name(self):
+ return "invoke_get_%s" % self.type
+ def getter_signature(self, name):
+ sig = "void (*%s)(struct sbus_request *, void *data, %s *" % (name, self.sssd_type)
+ if self.is_array:
+ sig += " *, int *"
+ sig += ")"
+ return sig
class Interface(Base):
def __init__(self, name):
@@ -237,6 +247,9 @@ def method_function_pointer(meth, name, with_names=False):
with_names and "data" or "",
method_arg_types(meth.in_args, with_names))
+def property_handlers(prop):
+ return prop.getter_signature(prop.getter_name())
+
def forward_method_invoker(signature, args):
out("")
out("/* invokes a handler with a '%s' DBus signature */", signature)
@@ -280,49 +293,36 @@ def source_method_invoker(signature, args):
def source_getter_invoker(prop):
out("")
- out("/* invokes a getter with a '%s' DBus type */", type)
- out("static int invoke_%s_getter(struct sbus_request *request, struct sbus_interface *intf, void *function_ptr)", prop.type)
+ if prop.is_array:
+ out("/* invokes a getter with an array of '%s' DBus type */", prop.dbus_type)
+ else:
+ out("/* invokes a getter with a '%s' DBus type */", prop.dbus_type)
+ out("static int %s(struct sbus_request *dbus_req, void *function_ptr)",
+ prop.getter_invoker_name())
out("{")
- out(" DBusError error = DBUS_ERROR_INIT;")
- out(" int ret;")
- for i in range(0, len(args)):
- arg = args[i]
- if arg.is_array:
- out(" %s *arg_%d;", arg.dbus_type, i)
- out(" int len_%d;", i)
- else:
- out(" %s arg_%d;", arg.dbus_type, i)
- out(" int (*handler)(struct sbus_request *, void *%s) = function_ptr;", method_arg_types(args))
+ 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)
out("")
- out(" if (!dbus_message_get_args(request->message, &error,")
- for i in range(0, len(args)):
- arg = args[i]
- if arg.is_array:
- out(" DBUS_TYPE_ARRAY, %s, &arg_%d, &len_%d,",
- arg.dbus_constant, i, i)
- else:
- out(" %s, &arg_%d,", arg.dbus_constant, i)
- out(" DBUS_TYPE_INVALID)) {")
- out(" ret = sbus_request_fail_and_finish(request, error.name, error.message);")
- out(" dbus_error_free(&error);")
- out(" return ret;")
- out(" }")
+ out(" %s", prop.getter_signature("handler"), new_line=False)
+ out(" = function_ptr;")
out("")
- out(" ret = (handler)(request, intf", new_line=False)
- for i in range(0, len(args)):
- arg = args[i]
- out(",\n arg_%d", i, new_line=False)
- if arg.is_array:
- out(",\n len_%d", i, new_line=False)
+ out(" (handler)(dbus_req, dbus_req->intf->instance_data, &prop_val", new_line=False)
+ if prop.is_array:
+ out(", &prop_len", new_line=False)
out(");")
- out("")
- for i in range(0, len(args)):
- arg = args[i]
- if arg.type in ["as", "ao"]:
- out(" dbus_free_string_array((char **)arg_%d);", i)
- out(" return ret;")
+ out("")
+ out(" out_val = prop_val;")
+ if prop.is_array:
+ out(" return sbus_request_return_array_as_variant(dbus_req, %s, (uint8_t*)out_val, prop_len, sizeof(%s));", prop.dbus_constant, prop.sssd_type)
+ else:
+ out(" return sbus_request_return_as_variant(dbus_req, %s, &out_val);", prop.dbus_constant)
out("}")
def forward_method_invokers(ifaces):
@@ -342,6 +342,27 @@ def source_method_invokers(invokers):
for (signature, meth) in invokers.items():
source_method_invoker(signature, meth.in_args)
+def forward_prop_invoker(prop):
+ out("static int %s(struct sbus_request *dbus_req, void *function_ptr);",
+ prop.getter_invoker_name())
+
+def forward_prop_invokers(ifaces):
+ invokers = { }
+ for iface in ifaces:
+ for prop in iface.properties:
+ if not prop.is_basic:
+ continue
+ if prop.type in invokers:
+ continue
+ forward_prop_invoker(prop)
+ invokers[prop.type] = prop
+ return invokers
+
+def source_prop_invokers(invokers):
+ for (type, prop) in invokers.items():
+ if prop.readable:
+ source_getter_invoker(prop)
+
def source_finisher(meth):
out("")
out("int %s_finish(struct sbus_request *req%s)",
@@ -438,6 +459,7 @@ def source_signals(iface, signals):
def source_properties(iface, properties):
out("")
out("/* property info for %s */", iface.name)
+
out("const struct sbus_property_meta %s__properties[] = {", iface.c_name())
for prop in properties:
out(" {")
@@ -451,6 +473,14 @@ def source_properties(iface, properties):
out(" SBUS_PROPERTY_WRITABLE,")
else:
assert False, "should not be reached"
+ if prop.readable:
+ out(" offsetof(struct %s, %s),", iface.c_name(), prop.getter_name())
+ out(" %s,", prop.getter_invoker_name())
+ else:
+ out(" 0, /* not readable */")
+ out(" NULL, /* no invoker */")
+ out(" 0, /* not writable */")
+ out(" NULL, /* no invoker */")
out(" },")
out(" { NULL, }")
out("};")
@@ -491,7 +521,8 @@ def generate_source(ifaces, filename, include_header=None):
if include_header:
out("#include \"%s\"", os.path.basename(include_header))
- invokers = forward_method_invokers(ifaces)
+ meth_invokers = forward_method_invokers(ifaces)
+ prop_invokers = forward_prop_invokers(ifaces)
for iface in ifaces:
@@ -510,7 +541,8 @@ def generate_source(ifaces, filename, include_header=None):
# The sbus_interface structure
source_interface(iface)
- source_method_invokers(invokers)
+ source_method_invokers(meth_invokers)
+ source_prop_invokers(prop_invokers)
def header_finisher(iface, meth):
if meth.use_raw_handler():
@@ -529,6 +561,8 @@ def header_vtable(iface, methods):
# All methods
for meth in iface.methods:
out(" %s;", method_function_pointer(meth, meth.c_name(), with_names=True))
+ for prop in iface.properties:
+ out(" %s;", property_handlers(prop))
out("};")
@@ -584,7 +618,7 @@ def generate_header(ifaces, filename):
out(" */")
for iface in ifaces:
- if iface.methods:
+ if iface.methods or iface.properties:
header_vtable(iface, iface.methods)
for meth in iface.methods:
header_finisher(iface, meth)
diff --git a/src/sbus/sssd_dbus_meta.h b/src/sbus/sssd_dbus_meta.h
index 0ad21df97..4e170b7d6 100644
--- a/src/sbus/sssd_dbus_meta.h
+++ b/src/sbus/sssd_dbus_meta.h
@@ -60,6 +60,8 @@ struct sbus_property_meta {
const char *name;
const char *type;
int flags;
+ size_t vtable_offset_get;
+ sbus_method_invoker_fn invoker_get;
size_t vtable_offset_set;
sbus_method_invoker_fn invoker_set;
};
diff --git a/src/sbus/sssd_dbus_properties.c b/src/sbus/sssd_dbus_properties.c
index 835b3078b..bdd5b432f 100644
--- a/src/sbus/sssd_dbus_properties.c
+++ b/src/sbus/sssd_dbus_properties.c
@@ -105,6 +105,77 @@ dispatch_properties_set(struct sbus_connection *conn,
return EOK;
}
+static int
+dispatch_properties_get(struct sbus_connection *conn,
+ struct sbus_interface *intf,
+ DBusMessage *message)
+{
+ struct sbus_request *req;
+ const char *signature;
+ const struct sbus_interface_meta *meta;
+ DBusMessageIter iter;
+ sbus_msg_handler_fn handler_fn;
+ const struct sbus_property_meta *property;
+ const char *interface_name;
+ const char *property_name;
+
+ req = sbus_new_request(conn, intf, message);
+ if (req == NULL) {
+ return ENOMEM;
+ }
+
+ meta = intf->vtable->meta;
+
+ signature = dbus_message_get_signature(message);
+ /* Interface name, property name */
+ if (strcmp(signature, "ss") != 0) {
+ return sbus_request_fail_and_finish(req,
+ sbus_error_new(req,
+ DBUS_ERROR_INVALID_ARGS,
+ "Invalid argument types passed to Get method"));
+ }
+
+ dbus_message_iter_init(message, &iter);
+ dbus_message_iter_get_basic(&iter, &interface_name);
+ dbus_message_iter_next(&iter);
+ dbus_message_iter_get_basic(&iter, &property_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"));
+ }
+
+ property = sbus_meta_find_property(intf->vtable->meta, property_name);
+ if (property == NULL) {
+ return sbus_request_fail_and_finish(req,
+ sbus_error_new(req,
+ DBUS_ERROR_UNKNOWN_PROPERTY,
+ "No such property"));
+ }
+
+ if (!(property->flags & SBUS_PROPERTY_READABLE)) {
+ return sbus_request_fail_and_finish(req,
+ sbus_error_new(req,
+ DBUS_ERROR_ACCESS_DENIED,
+ "Property is not readable"));
+ }
+
+ handler_fn = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+ if (!handler_fn) {
+ return sbus_request_fail_and_finish(req,
+ sbus_error_new(req,
+ DBUS_ERROR_NOT_SUPPORTED,
+ "Not implemented"));
+ }
+
+ sbus_request_invoke_or_finish(req, handler_fn,
+ intf->instance_data,
+ property->invoker_get);
+ return EOK;
+}
+
int sbus_properties_dispatch(struct sbus_request *dbus_req)
{
const char *member;
@@ -116,6 +187,10 @@ int sbus_properties_dispatch(struct sbus_request *dbus_req)
return dispatch_properties_set(dbus_req->conn,
dbus_req->intf,
dbus_req->message);
+ } else if (strcmp (member, "Get") == 0) {
+ return dispatch_properties_get(dbus_req->conn,
+ dbus_req->intf,
+ dbus_req->message);
}
return ERR_SBUS_NOSUP;