summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStef Walter <stefw@redhat.com>2014-01-10 08:54:41 +0100
committerJakub Hrozek <jhrozek@redhat.com>2014-02-24 11:14:49 +0100
commitfcd8093c58638dc7c4f9cddfc97f273b94ce2ead (patch)
tree9f8374be57b0a48f19cd861ae4d38f666ae7af5e
parentb699c4d7f85a5404be1d1ee9450331aea869b886 (diff)
downloadsssd-fcd8093c58638dc7c4f9cddfc97f273b94ce2ead.tar.gz
sssd-fcd8093c58638dc7c4f9cddfc97f273b94ce2ead.tar.xz
sssd-fcd8093c58638dc7c4f9cddfc97f273b94ce2ead.zip
sbus: Add sbus_vtable and update codegen to support it
Each interface is a vtable structure derived from sbus_vtable, in the sense that it has an sbus_vtable struct as its first argument. This lets us upcast the interface vtable structure to an sbus_vtable and dispatch to it dynamically and cleanly. The interface metadata contains information about which vtable offset in the interface metadata should be dispatched to for a given function. This is a common scheme, not only among dbus implementations, but also compiled languages. Currently all the vtable functions are of type sbus_msg_handler_fn. These are the handlers we are familiar with and perform raw processing of the message. Later commits will introduce type safe handlers that levelage compile checking and automatic argument packing/unpacking. Although this may seem contrived now, the remainder of the dbus infrastructure work will build on this, including ofd.Properties, ofd.ObjectManager, ofd.Introspect, compiler checked type safe unpacking/packing, etc. The codegen now generates vtable structures for each interface along-side the metadata, and fills in vtable offsets appropriately. It is obviously still possible to hand-craft such vtables and metadata if needed for a special case. Once again examples output can be found at: src/tests/sbus_codegen_tests_generated.h Reviewed-by: Jakub Hrozek <jhrozek@redhat.com> Reviewed-by: Sumit Bose <sbose@redhat.com> Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com> Reviewed-by: Simo Sorce <simo@redhat.com>
-rw-r--r--Makefile.am2
-rwxr-xr-xsrc/sbus/sbus_codegen42
-rw-r--r--src/sbus/sssd_dbus.h15
-rw-r--r--src/sbus/sssd_dbus_meta.h1
-rw-r--r--src/tests/sbus_codegen_tests.c33
-rwxr-xr-xsrc/tests/sbus_codegen_tests.xml5
-rw-r--r--src/tests/sbus_codegen_tests_generated.c8
-rw-r--r--src/tests/sbus_codegen_tests_generated.h19
8 files changed, 122 insertions, 3 deletions
diff --git a/Makefile.am b/Makefile.am
index d7e624367..18f7a40af 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -680,7 +680,7 @@ SUFFIXES = .xml _generated.h _generated.c
.xml_generated.h:
$(srcdir)/$(SBUS_CODEGEN) --mode=header --output=$@ $<
.xml_generated.c:
- $(srcdir)/$(SBUS_CODEGEN) --mode=source --output=$@ $<
+ $(srcdir)/$(SBUS_CODEGEN) --mode=source --include=$(@:.c=.h) --output=$@ $<
# Regenerate when codegen changes
CODEGEN_CODE = \
diff --git a/src/sbus/sbus_codegen b/src/sbus/sbus_codegen
index a1e2d02a0..86aeff094 100755
--- a/src/sbus/sbus_codegen
+++ b/src/sbus/sbus_codegen
@@ -184,6 +184,7 @@ def source_methods(iface, methods):
out(" %s__out,", meth.fq_c_name())
else:
out(" NULL, /* no out_args */")
+ out(" offsetof(struct %s, %s),", iface.c_name(), meth.c_name())
out(" },")
out(" { NULL, }")
out("};")
@@ -251,7 +252,7 @@ def source_interface(iface):
out(" NULL, /* no propetries */")
out("};")
-def generate_source(ifaces, filename):
+def generate_source(ifaces, filename, include_header=None):
basename = os.path.basename(filename)
out("/* The following definitions are auto-generated from %s */", basename)
@@ -260,6 +261,8 @@ def generate_source(ifaces, filename):
out("#include \"util/util.h\"")
out("#include \"sbus/sssd_dbus.h\"")
out("#include \"sbus/sssd_dbus_meta.h\"")
+ if include_header:
+ out("#include \"%s\"", os.path.basename(include_header))
for iface in ifaces:
@@ -278,6 +281,20 @@ def generate_source(ifaces, filename):
# The sbus_interface structure
source_interface(iface)
+def header_vtable(iface, methods):
+ out("")
+ out("/* vtable for %s */", iface.name)
+ out("struct %s {", iface.c_name())
+ out(" struct sbus_vtable vtable; /* derive from sbus_vtable */")
+
+ # All methods
+ for meth in iface.methods:
+ out(" sbus_msg_handler_fn %s;", meth.c_name())
+
+ # TODO: Property getters and setters will go here
+
+ out("};")
+
def generate_header(ifaces, filename):
basename = os.path.basename(filename)
guard = "__%s__" % re.sub(r'([^_A-Z0-9])', "_", basename.upper())
@@ -291,6 +308,23 @@ def generate_header(ifaces, filename):
out("")
out("/* ------------------------------------------------------------------------")
+ out(" * DBus Vtable handler structures")
+ out(" *")
+ out(" * These structures are filled in by implementors of the different")
+ out(" * dbus interfaces to handle method calls.")
+ out(" *")
+ out(" * Handler functions of type sbus_msg_handler_fn accept raw messages,")
+ out(" * other handlers will be typed appropriately. If a handler that is")
+ out(" * set to NULL is invoked it will result in a")
+ out(" * org.freedesktop.DBus.Error.NotSupported error for the caller.")
+ out(" */")
+
+ for iface in ifaces:
+ if iface.methods:
+ header_vtable(iface, iface.methods)
+
+ out("")
+ out("/* ------------------------------------------------------------------------")
out(" * DBus Interface Metadata")
out(" *")
out(" * These structure definitions are filled in with the information about")
@@ -465,6 +499,10 @@ def parse_options():
dest="output", default=None,
help="Set output file name (default: stdout)",
metavar="FILE")
+ parser.add_option("--include",
+ dest="include", default=None,
+ help="name of a header to #include",
+ metavar="HEADER")
(options, args) = parser.parse_args()
if not args:
@@ -488,7 +526,7 @@ def main():
if options.mode == "header":
generate_header(parser.parsed_interfaces, filename)
elif options.mode == "source":
- generate_source(parser.parsed_interfaces, filename)
+ generate_source(parser.parsed_interfaces, filename, options.include)
else:
assert False, "should not be reached"
diff --git a/src/sbus/sssd_dbus.h b/src/sbus/sssd_dbus.h
index 7604797c1..e9e7c9867 100644
--- a/src/sbus/sssd_dbus.h
+++ b/src/sbus/sssd_dbus.h
@@ -55,6 +55,21 @@ enum {
SBUS_RECONNECT_ERROR
};
+/*
+ * This represents vtable of interface handlers for methods and
+ * properties and so on. The actual vtable structs derive from this struct
+ * (ie: have this struct as their first member).
+ *
+ * The offsets for matching vtable function pointers are in sbus_method_meta
+ * These are used to dynamically dispatch the method invocations.
+ */
+struct sbus_vtable {
+ const struct sbus_interface_meta *meta;
+ int flags; /* unused for now */
+
+ /* derived structs place function pointers here. */
+};
+
/* Special interface and method for D-BUS introspection */
#define DBUS_INTROSPECT_INTERFACE "org.freedesktop.DBus.Introspectable"
#define DBUS_INTROSPECT_METHOD "Introspect"
diff --git a/src/sbus/sssd_dbus_meta.h b/src/sbus/sssd_dbus_meta.h
index 17ea7a507..abc992137 100644
--- a/src/sbus/sssd_dbus_meta.h
+++ b/src/sbus/sssd_dbus_meta.h
@@ -42,6 +42,7 @@ struct sbus_method_meta {
const char *name;
const struct sbus_arg_meta *in_args;
const struct sbus_arg_meta *out_args;
+ size_t vtable_offset;
};
enum {
diff --git a/src/tests/sbus_codegen_tests.c b/src/tests/sbus_codegen_tests.c
index 6b2abf8bc..39856fac7 100644
--- a/src/tests/sbus_codegen_tests.c
+++ b/src/tests/sbus_codegen_tests.c
@@ -112,6 +112,38 @@ START_TEST(test_signals)
}
END_TEST
+static int
+mock_move_universe(DBusMessage *msg, struct sbus_connection *conn)
+{
+ /* not called */
+ return 0;
+}
+
+static int
+mock_crash_now(DBusMessage *msg, struct sbus_connection *conn)
+{
+ /* not called */
+ return 0;
+}
+
+START_TEST(test_vtable)
+{
+ struct com_planetexpress_Ship vtable = {
+ { &com_planetexpress_Ship_meta, 0 },
+ mock_move_universe,
+ mock_crash_now,
+ };
+
+ /*
+ * These are not silly tests:
+ * - Will fail compilation if c-symbol name was not respected
+ * - Will fail if method order was not respected
+ */
+ ck_assert(vtable.crash_now == mock_crash_now);
+ ck_assert(vtable.MoveUniverse == mock_move_universe);
+}
+END_TEST
+
Suite *create_suite(void)
{
Suite *s = suite_create("sbus_codegen");
@@ -123,6 +155,7 @@ Suite *create_suite(void)
tcase_add_test(tc, test_methods);
tcase_add_test(tc, test_properties);
tcase_add_test(tc, test_signals);
+ tcase_add_test(tc, test_vtable);
/* Add all test cases to the test suite */
suite_add_tcase(s, tc);
diff --git a/src/tests/sbus_codegen_tests.xml b/src/tests/sbus_codegen_tests.xml
index 0def3585a..e571dbc17 100755
--- a/src/tests/sbus_codegen_tests.xml
+++ b/src/tests/sbus_codegen_tests.xml
@@ -29,6 +29,11 @@
<signal name="BecameSentient">
<arg name="gender" type="s"/>
</signal>
+
+ <!-- A method with a specific c name -->
+ <method name="Crash">
+ <annotation value="crash_now" name="org.freedesktop.DBus.GLib.CSymbol"/>
+ </method>
</interface>
<!--
diff --git a/src/tests/sbus_codegen_tests_generated.c b/src/tests/sbus_codegen_tests_generated.c
index 556eea12c..ccf612996 100644
--- a/src/tests/sbus_codegen_tests_generated.c
+++ b/src/tests/sbus_codegen_tests_generated.c
@@ -3,6 +3,7 @@
#include "util/util.h"
#include "sbus/sssd_dbus.h"
#include "sbus/sssd_dbus_meta.h"
+#include "sbus_codegen_tests_generated.h"
/* arguments for com.planetexpress.Ship.MoveUniverse */
const struct sbus_arg_meta com_planetexpress_Ship_MoveUniverse__in[] = {
@@ -23,6 +24,13 @@ const struct sbus_method_meta com_planetexpress_Ship__methods[] = {
"MoveUniverse", /* name */
com_planetexpress_Ship_MoveUniverse__in,
com_planetexpress_Ship_MoveUniverse__out,
+ offsetof(struct com_planetexpress_Ship, MoveUniverse),
+ },
+ {
+ "Crash", /* name */
+ NULL, /* no in_args */
+ NULL, /* no out_args */
+ offsetof(struct com_planetexpress_Ship, crash_now),
},
{ NULL, }
};
diff --git a/src/tests/sbus_codegen_tests_generated.h b/src/tests/sbus_codegen_tests_generated.h
index c3a23c870..3f7621588 100644
--- a/src/tests/sbus_codegen_tests_generated.h
+++ b/src/tests/sbus_codegen_tests_generated.h
@@ -6,6 +6,25 @@
#include "sbus/sssd_dbus.h"
/* ------------------------------------------------------------------------
+ * DBus Vtable handler structures
+ *
+ * These structures are filled in by implementors of the different
+ * dbus interfaces to handle method calls.
+ *
+ * Handler functions of type sbus_msg_handler_fn accept raw messages,
+ * other handlers will be typed appropriately. If a handler that is
+ * set to NULL is invoked it will result in a
+ * org.freedesktop.DBus.Error.NotSupported error for the caller.
+ */
+
+/* vtable for com.planetexpress.Ship */
+struct com_planetexpress_Ship {
+ struct sbus_vtable vtable; /* derive from sbus_vtable */
+ sbus_msg_handler_fn MoveUniverse;
+ sbus_msg_handler_fn crash_now;
+};
+
+/* ------------------------------------------------------------------------
* DBus Interface Metadata
*
* These structure definitions are filled in with the information about