Modified to support char type.
[platform/upstream/dbus.git] / mono / Handler.cs
1 namespace DBus
2 {
3   using System;
4   using System.Runtime.InteropServices;
5   using System.Diagnostics;
6   using System.Reflection;
7   using System.Collections;
8
9   internal class Handler
10   {
11     private string[] path = null;
12     private string pathName = null;
13     private Introspector introspector = null;
14     private object handledObject = null;
15     private DBusObjectPathVTable vTable;
16     private Connection connection;
17     private Service service;
18     private DBusHandleMessageFunction filterCalled;
19     
20     internal delegate void DBusObjectPathUnregisterFunction(IntPtr rawConnection,
21                                                             IntPtr userData);
22
23     internal delegate int DBusObjectPathMessageFunction(IntPtr rawConnection,
24                                                         IntPtr rawMessage,
25                                                         IntPtr userData);
26
27     internal delegate int DBusHandleMessageFunction(IntPtr rawConnection,
28                                                     IntPtr rawMessage,
29                                                     IntPtr userData);
30
31
32     private enum Result 
33     {
34       Handled = 0,
35       NotYetHandled = 1,
36       NeedMemory = 2
37     }
38
39     [StructLayout (LayoutKind.Sequential)]
40     private struct DBusObjectPathVTable 
41     {
42       public DBusObjectPathUnregisterFunction unregisterFunction;
43       public DBusObjectPathMessageFunction messageFunction;
44       public IntPtr padding1;
45       public IntPtr padding2;
46       public IntPtr padding3;
47       public IntPtr padding4;
48     
49       public DBusObjectPathVTable(DBusObjectPathUnregisterFunction unregisterFunction,
50                                   DBusObjectPathMessageFunction messageFunction) 
51       {
52         this.unregisterFunction = unregisterFunction;
53         this.messageFunction = messageFunction;
54         this.padding1 = IntPtr.Zero;
55         this.padding2 = IntPtr.Zero;
56         this.padding3 = IntPtr.Zero;
57         this.padding4 = IntPtr.Zero;
58       }
59     }
60
61     ~Handler() 
62     {
63       if (Connection != null && Connection.RawConnection != IntPtr.Zero && path != null) {
64         dbus_connection_unregister_object_path(Connection.RawConnection,
65                                                Path);
66       } 
67     }
68
69     public Handler(object handledObject, 
70                        string pathName, 
71                        Service service)
72     {
73       Service = service;
74       Connection = service.Connection;
75       HandledObject = handledObject;
76
77       // Strip the leading / off if there is one and get the path as an array
78       pathName = pathName.TrimStart('/');
79       this.path = pathName.Split('/');
80       this.pathName = "/" + pathName;
81
82       // Create the vTable and register the path
83       vTable = new DBusObjectPathVTable(new DBusObjectPathUnregisterFunction(Unregister_Called), 
84                                         new DBusObjectPathMessageFunction(Message_Called));
85       
86       if (!dbus_connection_register_object_path(Connection.RawConnection,
87                                                 Path,
88                                                 ref vTable,
89                                                 IntPtr.Zero))
90         throw new OutOfMemoryException();
91       
92       // Setup the filter function
93       this.filterCalled = new DBusHandleMessageFunction(Filter_Called);
94       if (!dbus_connection_add_filter(Connection.RawConnection,
95                                       this.filterCalled,
96                                       IntPtr.Zero,
97                                       IntPtr.Zero))
98         throw new OutOfMemoryException();
99     }
100
101     public object HandledObject 
102     {
103       get {
104         return this.handledObject;
105       }
106       
107       set {
108         this.handledObject = value;
109         
110         object[] attributes;
111         
112         // Register the methods
113         this.introspector = Introspector.GetIntrospector(value.GetType());        
114       }
115     }
116     
117     public int Filter_Called(IntPtr rawConnection,
118                              IntPtr rawMessage,
119                              IntPtr userData) 
120     {
121       Message message = Message.Wrap(rawMessage, Service);
122       
123       if (message.Type == Message.MessageType.Signal) {
124         Signal signal = (Signal) message;
125       } else if (message.Type == Message.MessageType.MethodCall) {
126         MethodCall methodCall = (MethodCall) message;
127       }
128       
129       return (int) Result.NotYetHandled;
130     }
131
132     public void Unregister_Called(IntPtr rawConnection, 
133                                   IntPtr userData)
134     {
135       System.Console.WriteLine("FIXME: Unregister called.");
136     }
137
138     private int Message_Called(IntPtr rawConnection, 
139                                IntPtr rawMessage, 
140                                IntPtr userData) 
141     {
142       Message message = Message.Wrap(rawMessage, Service);
143
144       switch (message.Type) {
145       case Message.MessageType.Signal:
146         System.Console.WriteLine("FIXME: Signal called.");
147         break;
148       case Message.MessageType.MethodCall:
149         return (int) HandleMethod((MethodCall) message);
150       }
151
152       return (int) Result.NotYetHandled;
153     }
154     
155     private Result HandleMethod(MethodCall methodCall)
156     {
157       methodCall.Service = service;
158       
159       InterfaceProxy interfaceProxy = this.introspector.GetInterface(methodCall.InterfaceName);
160       if (interfaceProxy == null || !interfaceProxy.HasMethod(methodCall.Key)) {
161         // No such interface here.
162         return Result.NotYetHandled;
163       }
164       
165       MethodInfo method = interfaceProxy.GetMethod(methodCall.Key);
166
167       // Now call the method. FIXME: Error handling
168       object [] args = methodCall.Arguments.GetParameters(method);
169       object retVal = method.Invoke(this.handledObject, args);
170
171       // Create the reply and send it
172       MethodReturn methodReturn = new MethodReturn(methodCall);
173       methodReturn.Arguments.AppendResults(method, retVal, args);
174       methodReturn.Send();
175
176       return Result.Handled;
177     }
178
179     internal string[] Path 
180     {
181       get 
182         {
183           return path;
184         }
185     }
186
187     public string PathName
188     {
189       get
190         {
191           return pathName;
192         }
193     }
194
195     internal Connection Connection 
196     {
197       get
198         {
199           return connection;
200         }
201       
202       set 
203         {
204           this.connection = value;
205         }
206     }
207
208     public Service Service
209     {
210       get
211         {
212           return service;
213         }
214       
215       set 
216         {
217           this.service = value;
218         }
219     }    
220
221     [DllImport ("dbus-1")]
222     private extern static bool dbus_connection_register_object_path (IntPtr rawConnection, string[] path, ref DBusObjectPathVTable vTable, IntPtr userData);
223
224     [DllImport ("dbus-1")]
225     private extern static void dbus_connection_unregister_object_path (IntPtr rawConnection, string[] path);
226
227     [DllImport ("dbus-1")]
228     private extern static bool dbus_connection_add_filter(IntPtr rawConnection,
229                                                           DBusHandleMessageFunction filter,
230                                                           IntPtr userData,
231                                                           IntPtr freeData);
232
233   }
234 }