summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/sbus/sbus_codegen72
-rw-r--r--src/sbus/sssd_dbus.h4
-rw-r--r--src/sbus/sssd_dbus_connection.c17
-rw-r--r--src/sbus/sssd_dbus_meta.h2
-rw-r--r--src/sbus/sssd_dbus_private.h8
-rw-r--r--src/sbus/sssd_dbus_properties.c122
-rw-r--r--src/tests/sbus_codegen_tests_generated.c4
-rw-r--r--src/util/util_errors.c1
-rw-r--r--src/util/util_errors.h1
9 files changed, 212 insertions, 19 deletions
diff --git a/src/sbus/sbus_codegen b/src/sbus/sbus_codegen
index 6c4b8ec9a..96248a628 100755
--- a/src/sbus/sbus_codegen
+++ b/src/sbus/sbus_codegen
@@ -114,10 +114,9 @@ BASIC_TYPES = {
'o': ( "DBUS_TYPE_OBJECT_PATH", "const char *", "const char *" ),
}
-class Arg(Base):
- def __init__(self, method, name, type):
+class Typed(Base):
+ def __init__(self, name, type):
Base.__init__(self, name)
- self.method = method
self.type = type
self.is_basic = False
self.is_array = False
@@ -135,6 +134,11 @@ class Arg(Base):
else:
self.is_basic = True
+class Arg(Typed):
+ def __init__(self, method, name, type):
+ Typed.__init__(self, name, type)
+ self.method = method
+
class Method(Base):
def __init__(self, iface, name):
Base.__init__(self, name)
@@ -166,11 +170,10 @@ class Signal(Base):
def fq_c_name(self):
return "%s_%s" % (self.iface.c_name(), self.c_name())
-class Property(Base):
- def __init__(self, iface, name, signature, access):
- Base.__init__(self, name)
+class Property(Typed):
+ def __init__(self, iface, name, type, access):
+ Typed.__init__(self, name, type)
self.iface = iface
- self.signature = signature
self.readable = False
self.writable = False
if access == 'readwrite':
@@ -234,7 +237,7 @@ def method_function_pointer(meth, name, with_names=False):
with_names and "data" or "",
method_arg_types(meth.in_args, with_names))
-def forward_invoker(signature, args):
+def forward_method_invoker(signature, args):
out("")
out("/* invokes a handler with a '%s' DBus signature */", signature)
out("static int invoke_%s_method(struct sbus_request *dbus_req, void *function_ptr);", signature)
@@ -275,6 +278,53 @@ def source_method_invoker(signature, args):
out(");")
out("}")
+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)
+ 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))
+ 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("")
+
+ 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(");")
+ 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("}")
+
def forward_method_invokers(ifaces):
invokers = { }
for iface in ifaces:
@@ -284,7 +334,7 @@ def forward_method_invokers(ifaces):
signature = meth.in_signature()
if signature in invokers:
continue
- forward_invoker(signature, meth.in_args)
+ forward_method_invoker(signature, meth.in_args)
invokers[signature] = meth
return invokers
@@ -392,7 +442,7 @@ def source_properties(iface, properties):
for prop in properties:
out(" {")
out(" \"%s\", /* name */", prop.name)
- out(" \"%s\", /* signature */", prop.signature)
+ out(" \"%s\", /* type */", prop.type)
if prop.readable and prop.writable:
out(" SBUS_PROPERTY_READABLE | SBUS_PROPERTY_WRITABLE,")
elif prop.readable:
@@ -480,8 +530,6 @@ def header_vtable(iface, methods):
for meth in iface.methods:
out(" %s;", method_function_pointer(meth, meth.c_name(), with_names=True))
- # TODO: Property getters and setters will go here
-
out("};")
def header_constants(iface):
diff --git a/src/sbus/sssd_dbus.h b/src/sbus/sssd_dbus.h
index a19f1d9c6..9c236479e 100644
--- a/src/sbus/sssd_dbus.h
+++ b/src/sbus/sssd_dbus.h
@@ -80,6 +80,9 @@ struct sbus_vtable {
#define DBUS_INTROSPECT_INTERFACE "org.freedesktop.DBus.Introspectable"
#define DBUS_INTROSPECT_METHOD "Introspect"
+/* Special interface and method for D-BUS properties */
+#define DBUS_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
+
struct sbus_interface {
const char *path;
struct sbus_vtable *vtable;
@@ -257,6 +260,7 @@ int sbus_request_return_array_as_variant(struct sbus_request *dbus_req,
const size_t item_size);
/*
+
* Return an error for a DBus method call request. The @error is a normal
* DBusError.
*
diff --git a/src/sbus/sssd_dbus_connection.c b/src/sbus/sssd_dbus_connection.c
index 4d3782e56..af1c8c56a 100644
--- a/src/sbus/sssd_dbus_connection.c
+++ b/src/sbus/sssd_dbus_connection.c
@@ -437,6 +437,7 @@ DBusHandlerResult sbus_message_handler(DBusConnection *dbus_conn,
/* Validate the method interface */
if (strcmp(msg_interface, intf_p->intf->vtable->meta->name) == 0 ||
+ strcmp(msg_interface, DBUS_PROPERTIES_INTERFACE) == 0 ||
(strcmp(msg_interface, DBUS_INTROSPECT_INTERFACE) == 0 &&
strcmp(msg_method, DBUS_INTROSPECT_METHOD) == 0)) {
@@ -510,11 +511,7 @@ static void sbus_handler_got_caller_id(struct tevent_req *req)
dbus_error = DBUS_ERROR_NOT_SUPPORTED;
goto fail;
}
- } else {
- /* Special case: check for Introspection request
- * This is usually only useful for system bus connections
- */
- if (strcmp(msg_interface, DBUS_INTROSPECT_INTERFACE) == 0 &&
+ } else if (strcmp(msg_interface, DBUS_INTROSPECT_INTERFACE) == 0 &&
strcmp(msg_method, DBUS_INTROSPECT_METHOD) == 0) {
DEBUG(SSSDBG_TRACE_LIBS, "Got introspection request\n");
ictx = talloc(dbus_req->conn, struct sbus_introspect_ctx);
@@ -527,7 +524,17 @@ static void sbus_handler_got_caller_id(struct tevent_req *req)
ictx->iface = interface;
handler_data = ictx;
method = &introspect_method;
+ } else if (strcmp(msg_interface, DBUS_PROPERTIES_INTERFACE) == 0) {
+ ret = sbus_properties_dispatch(dbus_req);
+ if (ret == ERR_SBUS_NOSUP) {
+ /* No known method matched */
+ dbus_error = DBUS_ERROR_NOT_SUPPORTED;
+ goto fail;
}
+ /* sbus_properties_dispatch handles all other errors
+ * or success internally
+ */
+ return;
}
if (handler_fn == NULL) {
diff --git a/src/sbus/sssd_dbus_meta.h b/src/sbus/sssd_dbus_meta.h
index 997aa9e46..0ad21df97 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_set;
+ sbus_method_invoker_fn invoker_set;
};
struct sbus_signal_meta {
diff --git a/src/sbus/sssd_dbus_private.h b/src/sbus/sssd_dbus_private.h
index 65189b5ff..fa11bc1c8 100644
--- a/src/sbus/sssd_dbus_private.h
+++ b/src/sbus/sssd_dbus_private.h
@@ -68,6 +68,10 @@ 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 {
@@ -137,4 +141,8 @@ struct tevent_req *sbus_get_sender_id_send(TALLOC_CTX *mem_ctx,
const char *sender);
int sbus_get_sender_id_recv(struct tevent_req *req, int64_t *_uid);
+/* =Properties============================================================ */
+
+int sbus_properties_dispatch(struct sbus_request *dbus_req);
+
#endif /* _SSSD_DBUS_PRIVATE_H_ */
diff --git a/src/sbus/sssd_dbus_properties.c b/src/sbus/sssd_dbus_properties.c
new file mode 100644
index 000000000..835b3078b
--- /dev/null
+++ b/src/sbus/sssd_dbus_properties.c
@@ -0,0 +1,122 @@
+/*
+ Authors:
+ Stef Walter <stefw@redhat.com>
+
+ Copyright (C) 2014 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "util/util.h"
+#include "sbus/sssd_dbus.h"
+#include "sbus/sssd_dbus_meta.h"
+#include "sbus/sssd_dbus_private.h"
+
+static int
+dispatch_properties_set(struct sbus_connection *conn,
+ struct sbus_interface *intf,
+ DBusMessage *message)
+{
+ const char *signature;
+ const struct sbus_interface_meta *meta;
+ const struct sbus_property_meta *property;
+ const char *interface_name;
+ const char *property_name;
+ const char *type;
+ struct sbus_request *req;
+ sbus_msg_handler_fn handler_fn;
+ DBusMessageIter iter;
+ DBusMessageIter variant;
+
+ req = sbus_new_request(conn, intf, message);
+ if (!req)
+ return ENOMEM;
+
+ meta = intf->vtable->meta;
+
+ signature = dbus_message_get_signature(message);
+ if (strcmp (signature, "ssv") != 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);
+ dbus_message_iter_next (&iter);
+ dbus_message_iter_get_basic (&iter, &property_name);
+ dbus_message_iter_next (&iter);
+
+ 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_WRITABLE)) {
+ return sbus_request_fail_and_finish(req,
+ sbus_error_new(req,
+ DBUS_ERROR_PROPERTY_READ_ONLY,
+ "Property is not writable"));
+ }
+
+ dbus_message_iter_recurse(&iter, &variant);
+ type = dbus_message_iter_get_signature (&variant);
+ if (strcmp (property->type, type) != 0) {
+ return sbus_request_fail_and_finish(req,
+ sbus_error_new(req,
+ DBUS_ERROR_INVALID_ARGS,
+ "Invalid data type for property"));
+ }
+
+ handler_fn = VTABLE_FUNC(intf->vtable, property->vtable_offset_set);
+ 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_set);
+ return EOK;
+}
+
+int sbus_properties_dispatch(struct sbus_request *dbus_req)
+{
+ const char *member;
+
+ member = dbus_message_get_member(dbus_req->message);
+
+ /* Set is handled a lot like a method invocation */
+ if (strcmp(member, "Set") == 0) {
+ return dispatch_properties_set(dbus_req->conn,
+ dbus_req->intf,
+ dbus_req->message);
+ }
+
+ return ERR_SBUS_NOSUP;
+}
diff --git a/src/tests/sbus_codegen_tests_generated.c b/src/tests/sbus_codegen_tests_generated.c
index 4ba257748..40d40cdc4 100644
--- a/src/tests/sbus_codegen_tests_generated.c
+++ b/src/tests/sbus_codegen_tests_generated.c
@@ -94,7 +94,7 @@ const struct sbus_signal_meta com_planetexpress_Ship__signals[] = {
const struct sbus_property_meta com_planetexpress_Ship__properties[] = {
{
"Color", /* name */
- "s", /* signature */
+ "s", /* type */
SBUS_PROPERTY_READABLE,
},
{ NULL, }
@@ -231,7 +231,7 @@ const struct sbus_method_meta test_pilot__methods[] = {
const struct sbus_property_meta test_pilot__properties[] = {
{
"FullName", /* name */
- "s", /* signature */
+ "s", /* type */
SBUS_PROPERTY_READABLE | SBUS_PROPERTY_WRITABLE,
},
{ NULL, }
diff --git a/src/util/util_errors.c b/src/util/util_errors.c
index 2b99faf74..113567423 100644
--- a/src/util/util_errors.c
+++ b/src/util/util_errors.c
@@ -59,6 +59,7 @@ struct err_string error_to_str[] = {
{ "Cannot get bus message sender" }, /* ERR_SBUS_GET_SENDER_ERROR */
{ "Bus message has no sender" }, /* ERR_SBUS_NO_SENDER */
{ "User/Group SIDs not found" }, /* ERR_NO_SIDS */
+ { "Bus method not supported" }, /* ERR_SBUS_NOSUP */
};
diff --git a/src/util/util_errors.h b/src/util/util_errors.h
index da518272b..b88c7969b 100644
--- a/src/util/util_errors.h
+++ b/src/util/util_errors.h
@@ -81,6 +81,7 @@ enum sssd_errors {
ERR_SBUS_GET_SENDER_ERROR,
ERR_SBUS_NO_SENDER,
ERR_NO_SIDS,
+ ERR_SBUS_NOSUP,
ERR_LAST /* ALWAYS LAST */
};