* qt/Makfile.am:
[platform/upstream/dbus.git] / mono / Connection.cs
1 namespace DBus 
2 {
3   
4   using System;
5   using System.Runtime.InteropServices;
6   using System.Diagnostics;
7   using System.Reflection;
8   using System.IO;
9   using System.Collections;
10   
11   public delegate int DBusHandleMessageFunction (IntPtr rawConnection,
12                                                  IntPtr rawMessage,
13                                                  IntPtr userData);
14
15   internal delegate void DBusObjectPathUnregisterFunction(IntPtr rawConnection,
16                                                           IntPtr userData);
17
18   internal delegate int DBusObjectPathMessageFunction(IntPtr rawConnection,
19                                                       IntPtr rawMessage,
20                                                       IntPtr userData);
21
22   [StructLayout (LayoutKind.Sequential)]
23   internal struct DBusObjectPathVTable
24   {
25     public DBusObjectPathUnregisterFunction unregisterFunction;
26     public DBusObjectPathMessageFunction messageFunction;
27     public IntPtr padding1;
28     public IntPtr padding2;
29     public IntPtr padding3;
30     public IntPtr padding4;
31     
32     public DBusObjectPathVTable(DBusObjectPathUnregisterFunction unregisterFunction,
33                                 DBusObjectPathMessageFunction messageFunction) 
34     {
35       this.unregisterFunction = unregisterFunction;
36       this.messageFunction = messageFunction;
37       this.padding1 = IntPtr.Zero;
38       this.padding2 = IntPtr.Zero;
39       this.padding3 = IntPtr.Zero;
40       this.padding4 = IntPtr.Zero;
41     }
42   }
43
44   public class Connection : IDisposable
45   {
46     /// <summary>
47     /// A pointer to the underlying Connection structure
48     /// </summary>
49     private IntPtr rawConnection;
50     
51     /// <summary>
52     /// The current slot number
53     /// </summary>
54     private static int slot = -1;
55     
56     private int timeout = -1;
57
58     private ArrayList filters = new ArrayList ();      // of DBusHandleMessageFunction
59     private ArrayList matches = new ArrayList ();      // of string
60     private Hashtable object_paths = new Hashtable (); // key: string  value: DBusObjectPathVTable
61
62     internal Connection(IntPtr rawConnection)
63     {
64       RawConnection = rawConnection;
65     }
66     
67     public Connection(string address)
68     {
69       // the assignment bumps the refcount
70       Error error = new Error();
71       error.Init();
72       RawConnection = dbus_connection_open(address, ref error);
73       if (RawConnection != IntPtr.Zero) {
74         dbus_connection_unref(RawConnection);
75       } else {
76         throw new DBusException(error);
77       }
78
79       SetupWithMain();
80     }
81
82     public void Dispose() 
83     {
84       Dispose(true);
85       GC.SuppressFinalize(this);
86     }
87     
88     public void Dispose (bool disposing) 
89     {
90       if (disposing && RawConnection != IntPtr.Zero) 
91         {
92           dbus_connection_disconnect(rawConnection);
93
94           RawConnection = IntPtr.Zero; // free the native object
95         }
96     }
97
98     public void Flush()
99     {
100       dbus_connection_flush(RawConnection);
101     }
102
103     public void SetupWithMain() 
104     {      
105       dbus_connection_setup_with_g_main(RawConnection, IntPtr.Zero);
106     }
107     
108     ~Connection () 
109     {
110       Dispose (false);
111     }
112     
113     internal static Connection Wrap(IntPtr rawConnection) 
114     {
115       if (slot > -1) {
116         // Maybe we already have a Connection object associated with
117         // this rawConnection then return it
118         IntPtr rawThis = dbus_connection_get_data (rawConnection, slot);
119         if (rawThis != IntPtr.Zero && ((GCHandle)rawThis).Target == typeof(DBus.Connection)) {
120           return (DBus.Connection) ((GCHandle)rawThis).Target;
121         }
122       }
123       
124       // If it doesn't exist then create a new connection around it
125       return new Connection(rawConnection);
126     }
127
128     public void AddFilter (DBusHandleMessageFunction func)
129     {
130       if (!dbus_connection_add_filter (RawConnection,
131                                        func,
132                                        IntPtr.Zero,
133                                        IntPtr.Zero))
134         throw new OutOfMemoryException ();
135
136       this.filters.Add (func);
137     }
138
139     public void RemoveFilter (DBusHandleMessageFunction func)
140     {
141       dbus_connection_remove_filter (RawConnection, func, IntPtr.Zero);
142
143       this.filters.Remove (func);
144     }
145
146     public void AddMatch (string match_rule)
147     {
148       dbus_bus_add_match (RawConnection, match_rule, IntPtr.Zero);
149
150       this.matches.Add (match_rule);
151     }
152
153     public void RemoveMatch (string match_rule)
154     {
155       dbus_bus_remove_match (RawConnection, match_rule, IntPtr.Zero);
156
157       this.matches.Remove (match_rule);
158     }
159
160     internal void RegisterObjectPath (string path, DBusObjectPathVTable vtable)
161     {
162       if (!dbus_connection_register_object_path (RawConnection, path, ref vtable, IntPtr.Zero))
163         throw new OutOfMemoryException ();
164  
165       this.object_paths[path] = vtable;
166     }
167  
168     internal void UnregisterObjectPath (string path)
169     {
170       dbus_connection_unregister_object_path (RawConnection, path);
171  
172       this.object_paths.Remove (path);
173     }
174
175
176     public string UniqueName
177     {
178       get
179         {
180           return Marshal.PtrToStringAnsi (dbus_bus_get_unique_name (RawConnection));
181         }
182     }
183
184     public int Timeout
185     {
186       get
187         {
188           return this.timeout;
189         }
190       set
191         {
192           this.timeout = value;
193         }
194     }
195     
196     private int Slot
197     {
198       get 
199         {
200           if (slot == -1) 
201             {
202               // We need to initialize the slot
203               if (!dbus_connection_allocate_data_slot (ref slot))
204                 throw new OutOfMemoryException ();
205               
206               Debug.Assert (slot >= 0);
207             }
208           
209           return slot;
210         }
211     }
212     
213     internal IntPtr RawConnection 
214     {
215       get 
216         {
217           return rawConnection;
218         }
219       set 
220         {
221           if (value == rawConnection)
222             return;
223           
224           if (rawConnection != IntPtr.Zero) 
225             {
226               // Remove our callbacks from this connection
227               foreach (DBusHandleMessageFunction func in this.filters)
228                 dbus_connection_remove_filter (rawConnection, func, IntPtr.Zero);
229
230               foreach (string match_rule in this.matches)
231                 dbus_bus_remove_match (rawConnection, match_rule, IntPtr.Zero);
232
233               foreach (string path in this.object_paths.Keys)
234                 dbus_connection_unregister_object_path (rawConnection, path);
235
236               // Get the reference to this
237               IntPtr rawThis = dbus_connection_get_data (rawConnection, Slot);
238               Debug.Assert (rawThis != IntPtr.Zero);
239               
240               // Blank over the reference
241               dbus_connection_set_data (rawConnection, Slot, IntPtr.Zero, IntPtr.Zero);
242               
243               // Free the reference
244               ((GCHandle) rawThis).Free();
245               
246               // Unref the connection
247               dbus_connection_unref(rawConnection);
248             }
249           
250           this.rawConnection = value;
251           
252           if (rawConnection != IntPtr.Zero) 
253             {
254               GCHandle rawThis;
255               
256               dbus_connection_ref (rawConnection);
257               
258               // We store a weak reference to the C# object on the C object
259               rawThis = GCHandle.Alloc (this, GCHandleType.WeakTrackResurrection);
260               
261               dbus_connection_set_data(rawConnection, Slot, (IntPtr) rawThis, IntPtr.Zero);
262
263               // Add the callbacks to this new connection
264               foreach (DBusHandleMessageFunction func in this.filters)
265                 dbus_connection_add_filter (rawConnection, func, IntPtr.Zero, IntPtr.Zero);
266
267               foreach (string match_rule in this.matches)
268                 dbus_bus_add_match (rawConnection, match_rule, IntPtr.Zero);
269
270               foreach (string path in this.object_paths.Keys) {
271                 DBusObjectPathVTable vtable = (DBusObjectPathVTable) this.object_paths[path];
272                 dbus_connection_register_object_path (rawConnection, path, ref vtable, IntPtr.Zero);
273               }
274             }
275           else
276             {
277               this.filters.Clear ();
278               this.matches.Clear ();
279               this.object_paths.Clear ();
280             }
281         }
282     }
283
284     [DllImport("dbus-glib-1")]
285     private extern static void dbus_connection_setup_with_g_main(IntPtr rawConnection,
286                                                              IntPtr rawContext);
287     
288     [DllImport ("dbus-1")]
289     private extern static IntPtr dbus_connection_open (string address, ref Error error);
290     
291     [DllImport ("dbus-1")]
292     private extern static void dbus_connection_unref (IntPtr ptr);
293     
294     [DllImport ("dbus-1")]
295     private extern static void dbus_connection_ref (IntPtr ptr);
296     
297     [DllImport ("dbus-1")]
298     private extern static bool dbus_connection_allocate_data_slot (ref int slot);
299     
300     [DllImport ("dbus-1")]
301     private extern static void dbus_connection_free_data_slot (ref int slot);
302     
303     [DllImport ("dbus-1")]
304     private extern static bool dbus_connection_set_data (IntPtr ptr,
305                                                          int    slot,
306                                                          IntPtr data,
307                                                          IntPtr free_data_func);
308     
309     [DllImport ("dbus-1")]
310     private extern static void dbus_connection_flush (IntPtr  ptr);
311     
312     [DllImport ("dbus-1")]
313     private extern static IntPtr dbus_connection_get_data (IntPtr ptr,
314                                                            int    slot);
315     
316     [DllImport ("dbus-1")]
317     private extern static void dbus_connection_disconnect (IntPtr ptr);
318
319     [DllImport ("dbus-1")]
320     private extern static IntPtr dbus_bus_get_unique_name (IntPtr ptr);
321
322     [DllImport("dbus-1")]
323     private extern static bool dbus_connection_add_filter(IntPtr rawConnection,
324                                                           DBusHandleMessageFunction filter,
325                                                           IntPtr userData,
326                                                           IntPtr freeData);
327
328     [DllImport("dbus-1")]
329     private extern static void dbus_connection_remove_filter(IntPtr rawConnection,
330                                                              DBusHandleMessageFunction filter,
331                                                              IntPtr userData);
332
333     [DllImport("dbus-1")]
334     private extern static void dbus_bus_add_match(IntPtr rawConnection,
335                                                   string rule,
336                                                   IntPtr erro);
337
338     [DllImport("dbus-1")]
339     private extern static void dbus_bus_remove_match(IntPtr rawConnection,
340                                                      string rule,
341                                                      IntPtr erro);
342
343     [DllImport ("dbus-1")]
344     private extern static bool dbus_connection_register_object_path (IntPtr rawConnection,
345                                                                      string path,
346                                                                      ref DBusObjectPathVTable vTable,
347                                                                      IntPtr userData);
348
349     [DllImport ("dbus-1")]
350     private extern static void dbus_connection_unregister_object_path (IntPtr rawConnection,
351                                                                        string path);
352
353   }
354 }