From c916037773d7d3d8d37ca2c5a8899b7b728e377d Mon Sep 17 00:00:00 2001 From: Owen Fraser-Green Date: Tue, 23 Mar 2004 12:10:32 +0000 Subject: First checkin of the Mono bindings. --- mono/Handler.cs | 256 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 256 insertions(+) create mode 100644 mono/Handler.cs (limited to 'mono/Handler.cs') diff --git a/mono/Handler.cs b/mono/Handler.cs new file mode 100644 index 00000000..d565b7ec --- /dev/null +++ b/mono/Handler.cs @@ -0,0 +1,256 @@ +namespace DBus +{ + using System; + using System.Runtime.InteropServices; + using System.Diagnostics; + using System.Reflection; + using System.Collections; + + internal class Handler + { + private string[] path = null; + private string pathName = null; + private Introspector introspector = null; + private object handledObject = null; + private Hashtable handledMethods = null; + private DBusObjectPathVTable vTable; + private Connection connection; + private Service service; + private DBusHandleMessageFunction filterCalled; + + internal delegate void DBusObjectPathUnregisterFunction(IntPtr rawConnection, + IntPtr userData); + + internal delegate int DBusObjectPathMessageFunction(IntPtr rawConnection, + IntPtr rawMessage, + IntPtr userData); + + internal delegate int DBusHandleMessageFunction(IntPtr rawConnection, + IntPtr rawMessage, + IntPtr userData); + + + private enum Result + { + Handled = 0, + NotYetHandled = 1, + NeedMemory = 2 + } + + [StructLayout (LayoutKind.Sequential)] + private struct DBusObjectPathVTable + { + public DBusObjectPathUnregisterFunction unregisterFunction; + public DBusObjectPathMessageFunction messageFunction; + public IntPtr padding1; + public IntPtr padding2; + public IntPtr padding3; + public IntPtr padding4; + + public DBusObjectPathVTable(DBusObjectPathUnregisterFunction unregisterFunction, + DBusObjectPathMessageFunction messageFunction) + { + this.unregisterFunction = unregisterFunction; + this.messageFunction = messageFunction; + this.padding1 = IntPtr.Zero; + this.padding2 = IntPtr.Zero; + this.padding3 = IntPtr.Zero; + this.padding4 = IntPtr.Zero; + } + } + + ~Handler() + { + if (Connection != null && Connection.RawConnection != IntPtr.Zero && path != null) { + dbus_connection_unregister_object_path(Connection.RawConnection, + Path); + } + } + + public Handler(object handledObject, + string pathName, + Service service) + { + Service = service; + Connection = service.Connection; + HandledObject = handledObject; + + // Strip the leading / off if there is one and get the path as an array + pathName = pathName.TrimStart('/'); + this.path = pathName.Split('/'); + this.pathName = "/" + pathName; + + // Create the vTable and register the path + vTable = new DBusObjectPathVTable(new DBusObjectPathUnregisterFunction(Unregister_Called), + new DBusObjectPathMessageFunction(Message_Called)); + + if (!dbus_connection_register_object_path(Connection.RawConnection, + Path, + ref vTable, + IntPtr.Zero)) + throw new OutOfMemoryException(); + + // Setup the filter function + this.filterCalled = new DBusHandleMessageFunction(Filter_Called); + if (!dbus_connection_add_filter(Connection.RawConnection, + this.filterCalled, + IntPtr.Zero, + IntPtr.Zero)) + throw new OutOfMemoryException(); + } + + private void RegisterMethod(MethodInfo method) + { + string key = method.Name + " " + Arguments.ParseParameters(method); + handledMethods.Add(key, method); + } + + public object HandledObject + { + get + { + return this.handledObject; + } + + set + { + this.handledObject = value; + + object[] attributes; + + // Register the methods + this.handledMethods = new Hashtable(); + this.introspector = new Introspector(value.GetType()); + + foreach (MethodInfo method in this.introspector.Methods) { + RegisterMethod(method); + } + } + } + + public int Filter_Called(IntPtr rawConnection, + IntPtr rawMessage, + IntPtr userData) + { + Message message = Message.Wrap(rawMessage, Service); + + if (message.Type == Message.MessageType.Signal) { + Signal signal = (Signal) message; + } else if (message.Type == Message.MessageType.MethodCall) { + MethodCall methodCall = (MethodCall) message; + } + + return (int) Result.NotYetHandled; + } + + public void Unregister_Called(IntPtr rawConnection, + IntPtr userData) + { + System.Console.WriteLine("FIXME: Unregister called."); + } + + private int Message_Called(IntPtr rawConnection, + IntPtr rawMessage, + IntPtr userData) + { + Message message = Message.Wrap(rawMessage, Service); + + switch (message.Type) { + case Message.MessageType.Signal: + System.Console.WriteLine("FIXME: Signal called."); + break; + case Message.MessageType.MethodCall: + return (int) HandleMethod((MethodCall) message); + } + + return (int) Result.NotYetHandled; + } + + private Result HandleMethod(MethodCall methodCall) + { + methodCall.Service = service; + + // Check the interface name matches + if (methodCall.InterfaceName != this.introspector.InterfaceName) { + return Result.NotYetHandled; + } + + // Iterate through getting the type codes + string key = methodCall.Name + " " + methodCall.Arguments; + + // Check it's one of our methods + if (!handledMethods.Contains(key)) { + return Result.NotYetHandled; + } + + // Got it! + MethodInfo method = (MethodInfo) handledMethods[key]; + + // Now call the method. FIXME: Error handling + object [] args = methodCall.Arguments.GetParameters(method); + object retVal = method.Invoke(this.handledObject, args); + + // Create the reply and send it + MethodReturn methodReturn = new MethodReturn(methodCall); + methodReturn.Arguments.AppendResults(method, retVal, args); + methodReturn.Send(); + + return Result.Handled; + } + + internal string[] Path + { + get + { + return path; + } + } + + public string PathName + { + get + { + return pathName; + } + } + + internal Connection Connection + { + get + { + return connection; + } + + set + { + this.connection = value; + } + } + + public Service Service + { + get + { + return service; + } + + set + { + this.service = value; + } + } + + [DllImport ("dbus-1")] + private extern static bool dbus_connection_register_object_path (IntPtr rawConnection, string[] path, ref DBusObjectPathVTable vTable, IntPtr userData); + + [DllImport ("dbus-1")] + private extern static void dbus_connection_unregister_object_path (IntPtr rawConnection, string[] path); + + [DllImport ("dbus-1")] + private extern static bool dbus_connection_add_filter(IntPtr rawConnection, + DBusHandleMessageFunction filter, + IntPtr userData, + IntPtr freeData); + + } +} -- cgit