Add basic server functionality.
This commit is contained in:
parent
5905d50e1a
commit
1457b249b7
4 changed files with 104 additions and 18 deletions
39
source/ddbus/bus.d
Normal file
39
source/ddbus/bus.d
Normal file
|
@ -0,0 +1,39 @@
|
|||
module ddbus.bus;
|
||||
|
||||
import ddbus.router;
|
||||
import ddbus.thin;
|
||||
import ddbus.c_lib;
|
||||
import std.string;
|
||||
|
||||
enum BusService = "org.freedesktop.DBus";
|
||||
enum BusPath = "/org/freedesktop/DBus";
|
||||
enum BusInterface = "org.freedesktop.DBus";
|
||||
|
||||
enum NameFlags {
|
||||
AllowReplace = 1, ReplaceExisting = 2, NoQueue = 4
|
||||
}
|
||||
|
||||
/// Requests a DBus well-known name.
|
||||
/// returns if the name is owned after the call.
|
||||
/// Involves blocking call on a DBus method, may throw an exception on failure.
|
||||
bool requestName(Connection conn, string name,
|
||||
NameFlags flags = NameFlags.NoQueue | NameFlags.AllowReplace) {
|
||||
auto msg = Message(BusService,BusPath,BusInterface,"RequestName");
|
||||
msg.build(name,cast(uint)(flags));
|
||||
auto res = conn.sendWithReplyBlocking(msg).to!uint;
|
||||
return (res == 1) || (res == 4);
|
||||
}
|
||||
|
||||
/// A simple main loop that isn't necessarily efficient
|
||||
/// and isn't guaranteed to work with other tasks and threads.
|
||||
/// Use only for apps that only do DBus triggered things.
|
||||
void simpleMainLoop(Connection conn) {
|
||||
while(dbus_connection_read_write_dispatch(conn.conn, -1)) {} // empty loop body
|
||||
}
|
||||
|
||||
unittest {
|
||||
import dunit.toolkit;
|
||||
Connection conn = connectToBus();
|
||||
conn.requestName("ca.thume.ddbus.testing").assertTrue();
|
||||
}
|
||||
|
|
@ -1,14 +1,16 @@
|
|||
module ddbus.router;
|
||||
|
||||
import ddbus.thin;
|
||||
import ddbus.c_lib;
|
||||
import std.string;
|
||||
import std.typecons;
|
||||
import core.memory;
|
||||
|
||||
struct MessagePattern {
|
||||
string sender;
|
||||
string path;
|
||||
string iface;
|
||||
string method;
|
||||
string sender;
|
||||
|
||||
this(Message msg) {
|
||||
path = msg.path();
|
||||
|
@ -21,6 +23,13 @@ struct MessagePattern {
|
|||
}
|
||||
}
|
||||
|
||||
this(string path, string iface, string method, string sender = null) {
|
||||
this.path = path;
|
||||
this.iface = iface;
|
||||
this.method = method;
|
||||
this.sender = sender;
|
||||
}
|
||||
|
||||
size_t toHash() const @safe nothrow {
|
||||
size_t hash = 0;
|
||||
auto stringHash = &(typeid(path).getHash);
|
||||
|
@ -38,14 +47,9 @@ struct MessagePattern {
|
|||
|
||||
class MessageRouter {
|
||||
alias HandlerFunc = void delegate(Message call, Connection conn);
|
||||
Connection conn;
|
||||
HandlerFunc[MessagePattern] callTable;
|
||||
|
||||
this(Connection conn) {
|
||||
this.conn = conn;
|
||||
}
|
||||
|
||||
bool handle(Message msg) {
|
||||
bool handle(Message msg, Connection conn) {
|
||||
MessageType type = msg.type();
|
||||
if(type != MessageType.Call && type != MessageType.Signal)
|
||||
return false;
|
||||
|
@ -56,7 +60,7 @@ class MessageRouter {
|
|||
return true;
|
||||
}
|
||||
|
||||
void setHandler(Ret, Args...)(MessagePattern patt, Connection conn, Ret delegate(Args) handler) {
|
||||
void setHandler(Ret, Args...)(MessagePattern patt, Ret delegate(Args) handler) {
|
||||
void handlerWrapper(Message call, Connection conn) {
|
||||
Tuple!Args args = call.readTuple!(Tuple!Args)();
|
||||
Ret ret = handler(args.expand);
|
||||
|
@ -70,10 +74,34 @@ class MessageRouter {
|
|||
}
|
||||
}
|
||||
|
||||
extern(C) private DBusHandlerResult filterFunc(DBusConnection *dConn, DBusMessage *dMsg, void *routerP) {
|
||||
MessageRouter router = cast(MessageRouter)routerP;
|
||||
dbus_message_ref(dMsg);
|
||||
Message msg = Message(dMsg);
|
||||
dbus_connection_ref(dConn);
|
||||
Connection conn = Connection(dConn);
|
||||
bool handled = router.handle(msg, conn);
|
||||
if(handled) {
|
||||
return DBusHandlerResult.DBUS_HANDLER_RESULT_HANDLED;
|
||||
} else {
|
||||
return DBusHandlerResult.DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
}
|
||||
}
|
||||
|
||||
extern(C) private void unrootUserData(void *userdata) {
|
||||
GC.removeRoot(userdata);
|
||||
}
|
||||
|
||||
void registerRouter(Connection conn, MessageRouter router) {
|
||||
void *routerP = cast(void*)router;
|
||||
GC.addRoot(routerP);
|
||||
dbus_connection_add_filter(conn.conn, &filterFunc, routerP, &unrootUserData);
|
||||
}
|
||||
|
||||
unittest {
|
||||
import dunit.toolkit;
|
||||
auto msg = Message("org.example.test", "/test","org.example.testing","testMethod");
|
||||
auto patt= MessagePattern(msg);
|
||||
auto patt= new MessagePattern(msg);
|
||||
patt.assertEqual(patt);
|
||||
patt.sender.assertNull();
|
||||
patt.path.assertEqual("/test");
|
||||
|
|
|
@ -94,27 +94,27 @@ struct Message {
|
|||
string signature() {
|
||||
const(char)* cStr = dbus_message_get_signature(msg);
|
||||
assert(cStr != null);
|
||||
return cStr.fromStringz().assumeUnique();
|
||||
return cStr.fromStringz().idup;
|
||||
}
|
||||
string path() {
|
||||
const(char)* cStr = dbus_message_get_path(msg);
|
||||
assert(cStr != null);
|
||||
return cStr.fromStringz().assumeUnique();
|
||||
return cStr.fromStringz().idup;
|
||||
}
|
||||
string iface() {
|
||||
const(char)* cStr = dbus_message_get_interface(msg);
|
||||
assert(cStr != null);
|
||||
return cStr.fromStringz().assumeUnique();
|
||||
return cStr.fromStringz().idup;
|
||||
}
|
||||
string member() {
|
||||
const(char)* cStr = dbus_message_get_member(msg);
|
||||
assert(cStr != null);
|
||||
return cStr.fromStringz().assumeUnique();
|
||||
return cStr.fromStringz().idup;
|
||||
}
|
||||
string sender() {
|
||||
const(char)* cStr = dbus_message_get_sender(msg);
|
||||
assert(cStr != null);
|
||||
return cStr.fromStringz().assumeUnique();
|
||||
return cStr.fromStringz().idup;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,7 +151,7 @@ struct Connection {
|
|||
dbus_connection_flush(conn);
|
||||
}
|
||||
|
||||
Message sendWithReplyBlocking(Message msg, int timeout = 100) {
|
||||
Message sendWithReplyBlocking(Message msg, int timeout = -1) {
|
||||
DBusMessage *dbusMsg = msg.msg;
|
||||
dbus_message_ref(dbusMsg);
|
||||
DBusMessage *reply = wrapErrors((err) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue