mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2025-12-24 20:30:07 +01:00
256 lines
6.4 KiB
C#
256 lines
6.4 KiB
C#
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);
|
|
|
|
}
|
|
}
|