diff --git a/source/ddbus/router.d b/source/ddbus/router.d index 92114f9..269a95a 100644 --- a/source/ddbus/router.d +++ b/source/ddbus/router.d @@ -8,6 +8,7 @@ import std.typecons; import core.memory; import std.array; import std.algorithm; +import std.format; struct MessagePattern { string path; @@ -44,6 +45,15 @@ struct MessagePattern { } } +unittest { + import dunit.toolkit; + auto msg = Message("org.example.test", "/test","org.example.testing","testMethod"); + auto patt= new MessagePattern(msg); + patt.assertEqual(patt); + patt.signal.assertFalse(); + patt.path.assertEqual("/test"); +} + struct MessageHandler { alias HandlerFunc = void delegate(Message call, Connection conn); HandlerFunc func; @@ -60,6 +70,13 @@ class MessageRouter { return false; auto pattern = MessagePattern(msg); // import std.stdio; debug writeln("Handling ", pattern); + + if(pattern.iface == "org.freedesktop.DBus.Introspectable" && + pattern.method == "Introspect" && !pattern.signal) { + handleIntrospect(pattern.path, conn); + return true; + } + MessageHandler* handler = (pattern in callTable); if(handler is null) return false; @@ -98,6 +115,50 @@ class MessageRouter { MessageHandler handleStruct = {func: &handlerWrapper, argSig: args, retSig: ret}; callTable[patt] = handleStruct; } + + static string introspectHeader = ` + +`; + + string introspectXML(string path) { + auto methods = callTable.byKey().filter!(a => (a.path == path) && !a.signal)().array() + // .schwartzSort!((a) => a.iface, "a a.iface < b.iface)().release(); + auto ifaces = groupBy!((a) => a.iface)(methods); + auto app = appender!string; + formattedWrite(app,introspectHeader,path); + foreach(iface; ifaces) { + formattedWrite(app,``,iface.front.iface); + foreach(methodPatt; iface) { + formattedWrite(app,``,methodPatt.method); + auto handler = callTable[methodPatt]; + foreach(arg; handler.argSig) { + formattedWrite(app,``,arg); + } + foreach(arg; handler.retSig) { + formattedWrite(app,``,arg); + } + app.put(""); + } + app.put(""); + } + + string childPath = path ~ "/"; + auto children = callTable.byKey().filter!(a => (a.path.startsWith(childPath)) && !a.signal)() + .map!((s) => s.path.chompPrefix(childPath)) + .map!((s) => s.splitter('/').front); + foreach(child; children) { + formattedWrite(app,``,child); + } + + app.put(""); + return app.data; + } + + void handleIntrospect(string path, Connection conn) { + // TODO + } } extern(C) private DBusHandlerResult filterFunc(DBusConnection *dConn, DBusMessage *dMsg, void *routerP) { @@ -124,11 +185,17 @@ void registerRouter(Connection conn, MessageRouter router) { dbus_connection_add_filter(conn.conn, &filterFunc, routerP, &unrootUserData); } -unittest { +unittest{ import dunit.toolkit; - auto msg = Message("org.example.test", "/test","org.example.testing","testMethod"); - auto patt= new MessagePattern(msg); - patt.assertEqual(patt); - patt.signal.assertFalse(); - patt.path.assertEqual("/test"); + auto router = new MessageRouter(); + // set up test messages + MessagePattern patt = MessagePattern("/root","ca.thume.test","test"); + router.setHandler!(int,int)(patt,(int p) {return 6;}); + patt = MessagePattern("/root","ca.thume.tester","lolwut"); + router.setHandler!(void,int,string)(patt,(int p, string p2) {}); + patt = MessagePattern("/root/wat","ca.thume.tester","lolwut"); + router.setHandler!(int,int)(patt,(int p) {return 6;}); + + // import std.stdio; + // writeln(router.introspectXML("/root")); }