1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
|
namespace DBus
{
using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Reflection;
using System.Collections;
internal enum Result
{
Handled = 0,
NotYetHandled = 1,
NeedMemory = 2
}
internal class Handler
{
private string path = null;
private Introspector introspector = null;
private object handledObject = null;
private DBusObjectPathVTable vTable;
private Connection connection;
private Service service;
// We need to hold extra references to these callbacks so that they don't
// get garbage collected before they are called back into from unmanaged
// code.
private DBusObjectPathUnregisterFunction unregister_func;
private DBusObjectPathMessageFunction message_func;
public Handler(object handledObject,
string path,
Service service)
{
Service = service;
Connection = service.Connection;
HandledObject = handledObject;
this.path = path;
// Create the vTable and register the path
this.unregister_func = new DBusObjectPathUnregisterFunction (Unregister_Called);
this.message_func = new DBusObjectPathMessageFunction (Message_Called);
vTable = new DBusObjectPathVTable (this.unregister_func, this.message_func);
Connection.RegisterObjectPath (Path, vTable);
RegisterSignalHandlers();
}
private void RegisterSignalHandlers()
{
ProxyBuilder proxyBuilder = new ProxyBuilder(Service, HandledObject.GetType(), Path);
foreach (DictionaryEntry interfaceEntry in this.introspector.InterfaceProxies) {
InterfaceProxy interfaceProxy = (InterfaceProxy) interfaceEntry.Value;
foreach (DictionaryEntry signalEntry in interfaceProxy.Signals) {
EventInfo eventE = (EventInfo) signalEntry.Value;
Delegate del = Delegate.CreateDelegate(eventE.EventHandlerType, proxyBuilder.GetSignalProxy(), "Proxy_" + eventE.Name);
eventE.AddEventHandler(HandledObject, del);
}
}
}
public object HandledObject
{
get {
return this.handledObject;
}
set {
this.handledObject = value;
// Register the methods
this.introspector = Introspector.GetIntrospector(value.GetType());
}
}
public void Unregister_Called(IntPtr rawConnection,
IntPtr userData)
{
if (service != null) {
service.UnregisterObject(HandledObject);
}
path = null;
}
private int Message_Called(IntPtr rawConnection,
IntPtr rawMessage,
IntPtr userData)
{
Message message = Message.Wrap(rawMessage, Service);
Result res = Result.NotYetHandled;
switch (message.Type) {
case Message.MessageType.MethodCall:
res = HandleMethod ((MethodCall) message);
break;
case Message.MessageType.Signal:
// We're not interested in signals here because we're the ones
// that generate them!
break;
}
message.Dispose ();
return (int) res;
}
private Result HandleMethod(MethodCall methodCall)
{
methodCall.Service = service;
InterfaceProxy interfaceProxy = this.introspector.GetInterface(methodCall.InterfaceName);
if (interfaceProxy == null || !interfaceProxy.HasMethod(methodCall.Key)) {
// No such interface here.
return Result.NotYetHandled;
}
MethodInfo method = interfaceProxy.GetMethod(methodCall.Key);
Message.Push (methodCall);
// Now call the method. FIXME: Error handling
object [] args = methodCall.Arguments.GetParameters(method);
object retVal = method.Invoke(this.handledObject, args);
Message.Pop ();
// 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;
}
}
internal Connection Connection
{
get
{
return connection;
}
set
{
this.connection = value;
}
}
public Service Service
{
get
{
return service;
}
set
{
this.service = value;
}
}
}
}
|