5 using System.Runtime.InteropServices;
6 using System.Diagnostics;
7 using System.Reflection;
9 using System.Collections;
11 public delegate int DBusHandleMessageFunction (IntPtr rawConnection,
15 internal delegate void DBusObjectPathUnregisterFunction(IntPtr rawConnection,
18 internal delegate int DBusObjectPathMessageFunction(IntPtr rawConnection,
22 [StructLayout (LayoutKind.Sequential)]
23 internal struct DBusObjectPathVTable
25 public DBusObjectPathUnregisterFunction unregisterFunction;
26 public DBusObjectPathMessageFunction messageFunction;
27 public IntPtr padding1;
28 public IntPtr padding2;
29 public IntPtr padding3;
30 public IntPtr padding4;
32 public DBusObjectPathVTable(DBusObjectPathUnregisterFunction unregisterFunction,
33 DBusObjectPathMessageFunction messageFunction)
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;
44 public class Connection : IDisposable
47 /// A pointer to the underlying Connection structure
49 private IntPtr rawConnection;
52 /// The current slot number
54 private static int slot = -1;
56 private int timeout = -1;
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
62 internal Connection(IntPtr rawConnection)
64 RawConnection = rawConnection;
67 public Connection(string address)
69 // the assignment bumps the refcount
70 Error error = new Error();
72 RawConnection = dbus_connection_open(address, ref error);
73 if (RawConnection != IntPtr.Zero) {
74 dbus_connection_unref(RawConnection);
76 throw new DBusException(error);
85 GC.SuppressFinalize(this);
88 public void Dispose (bool disposing)
90 if (disposing && RawConnection != IntPtr.Zero)
92 dbus_connection_disconnect(rawConnection);
94 RawConnection = IntPtr.Zero; // free the native object
100 dbus_connection_flush(RawConnection);
103 public void SetupWithMain()
105 dbus_connection_setup_with_g_main(RawConnection, IntPtr.Zero);
113 internal static Connection Wrap(IntPtr rawConnection)
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;
124 // If it doesn't exist then create a new connection around it
125 return new Connection(rawConnection);
128 public void AddFilter (DBusHandleMessageFunction func)
130 if (!dbus_connection_add_filter (RawConnection,
134 throw new OutOfMemoryException ();
136 this.filters.Add (func);
139 public void RemoveFilter (DBusHandleMessageFunction func)
141 dbus_connection_remove_filter (RawConnection, func, IntPtr.Zero);
143 this.filters.Remove (func);
146 public void AddMatch (string match_rule)
148 dbus_bus_add_match (RawConnection, match_rule, IntPtr.Zero);
150 this.matches.Add (match_rule);
153 public void RemoveMatch (string match_rule)
155 dbus_bus_remove_match (RawConnection, match_rule, IntPtr.Zero);
157 this.matches.Remove (match_rule);
160 internal void RegisterObjectPath (string path, DBusObjectPathVTable vtable)
162 if (!dbus_connection_register_object_path (RawConnection, path, ref vtable, IntPtr.Zero))
163 throw new OutOfMemoryException ();
165 this.object_paths[path] = vtable;
168 internal void UnregisterObjectPath (string path)
170 dbus_connection_unregister_object_path (RawConnection, path);
172 this.object_paths.Remove (path);
176 public string UniqueName
180 return Marshal.PtrToStringAnsi (dbus_bus_get_unique_name (RawConnection));
192 this.timeout = value;
202 // We need to initialize the slot
203 if (!dbus_connection_allocate_data_slot (ref slot))
204 throw new OutOfMemoryException ();
206 Debug.Assert (slot >= 0);
213 internal IntPtr RawConnection
217 return rawConnection;
221 if (value == rawConnection)
224 if (rawConnection != IntPtr.Zero)
226 // Remove our callbacks from this connection
227 foreach (DBusHandleMessageFunction func in this.filters)
228 dbus_connection_remove_filter (rawConnection, func, IntPtr.Zero);
230 foreach (string match_rule in this.matches)
231 dbus_bus_remove_match (rawConnection, match_rule, IntPtr.Zero);
233 foreach (string path in this.object_paths.Keys)
234 dbus_connection_unregister_object_path (rawConnection, path);
236 // Get the reference to this
237 IntPtr rawThis = dbus_connection_get_data (rawConnection, Slot);
238 Debug.Assert (rawThis != IntPtr.Zero);
240 // Blank over the reference
241 dbus_connection_set_data (rawConnection, Slot, IntPtr.Zero, IntPtr.Zero);
243 // Free the reference
244 ((GCHandle) rawThis).Free();
246 // Unref the connection
247 dbus_connection_unref(rawConnection);
250 this.rawConnection = value;
252 if (rawConnection != IntPtr.Zero)
256 dbus_connection_ref (rawConnection);
258 // We store a weak reference to the C# object on the C object
259 rawThis = GCHandle.Alloc (this, GCHandleType.WeakTrackResurrection);
261 dbus_connection_set_data(rawConnection, Slot, (IntPtr) rawThis, IntPtr.Zero);
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);
267 foreach (string match_rule in this.matches)
268 dbus_bus_add_match (rawConnection, match_rule, IntPtr.Zero);
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);
277 this.filters.Clear ();
278 this.matches.Clear ();
279 this.object_paths.Clear ();
284 [DllImport("dbus-glib-1")]
285 private extern static void dbus_connection_setup_with_g_main(IntPtr rawConnection,
288 [DllImport ("dbus-1")]
289 private extern static IntPtr dbus_connection_open (string address, ref Error error);
291 [DllImport ("dbus-1")]
292 private extern static void dbus_connection_unref (IntPtr ptr);
294 [DllImport ("dbus-1")]
295 private extern static void dbus_connection_ref (IntPtr ptr);
297 [DllImport ("dbus-1")]
298 private extern static bool dbus_connection_allocate_data_slot (ref int slot);
300 [DllImport ("dbus-1")]
301 private extern static void dbus_connection_free_data_slot (ref int slot);
303 [DllImport ("dbus-1")]
304 private extern static bool dbus_connection_set_data (IntPtr ptr,
307 IntPtr free_data_func);
309 [DllImport ("dbus-1")]
310 private extern static void dbus_connection_flush (IntPtr ptr);
312 [DllImport ("dbus-1")]
313 private extern static IntPtr dbus_connection_get_data (IntPtr ptr,
316 [DllImport ("dbus-1")]
317 private extern static void dbus_connection_disconnect (IntPtr ptr);
319 [DllImport ("dbus-1")]
320 private extern static IntPtr dbus_bus_get_unique_name (IntPtr ptr);
322 [DllImport("dbus-1")]
323 private extern static bool dbus_connection_add_filter(IntPtr rawConnection,
324 DBusHandleMessageFunction filter,
328 [DllImport("dbus-1")]
329 private extern static void dbus_connection_remove_filter(IntPtr rawConnection,
330 DBusHandleMessageFunction filter,
333 [DllImport("dbus-1")]
334 private extern static void dbus_bus_add_match(IntPtr rawConnection,
338 [DllImport("dbus-1")]
339 private extern static void dbus_bus_remove_match(IntPtr rawConnection,
343 [DllImport ("dbus-1")]
344 private extern static bool dbus_connection_register_object_path (IntPtr rawConnection,
346 ref DBusObjectPathVTable vTable,
349 [DllImport ("dbus-1")]
350 private extern static void dbus_connection_unregister_object_path (IntPtr rawConnection,