diff options
author | Stef Walter <stefw@redhat.com> | 2014-01-10 08:54:41 +0100 |
---|---|---|
committer | Jakub Hrozek <jhrozek@redhat.com> | 2014-02-24 11:14:49 +0100 |
commit | fcd8093c58638dc7c4f9cddfc97f273b94ce2ead (patch) | |
tree | 9f8374be57b0a48f19cd861ae4d38f666ae7af5e /src | |
parent | b699c4d7f85a5404be1d1ee9450331aea869b886 (diff) | |
download | sssd-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>
Diffstat (limited to 'src')
-rwxr-xr-x | src/sbus/sbus_codegen | 42 | ||||
-rw-r--r-- | src/sbus/sssd_dbus.h | 15 | ||||
-rw-r--r-- | src/sbus/sssd_dbus_meta.h | 1 | ||||
-rw-r--r-- | src/tests/sbus_codegen_tests.c | 33 | ||||
-rwxr-xr-x | src/tests/sbus_codegen_tests.xml | 5 | ||||
-rw-r--r-- | src/tests/sbus_codegen_tests_generated.c | 8 | ||||
-rw-r--r-- | src/tests/sbus_codegen_tests_generated.h | 19 |
7 files changed, 121 insertions, 2 deletions
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 |