Connection.cs

00001 namespace DBus 
00002 {
00003   
00004   using System;
00005   using System.Runtime.InteropServices;
00006   using System.Diagnostics;
00007   using System.Reflection;
00008   using System.IO;
00009   using System.Collections;
00010   
00011   public delegate int DBusHandleMessageFunction (IntPtr rawConnection,
00012                                                  IntPtr rawMessage,
00013                                                  IntPtr userData);
00014 
00015   internal delegate void DBusObjectPathUnregisterFunction(IntPtr rawConnection,
00016                                                           IntPtr userData);
00017 
00018   internal delegate int DBusObjectPathMessageFunction(IntPtr rawConnection,
00019                                                       IntPtr rawMessage,
00020                                                       IntPtr userData);
00021 
00022   [StructLayout (LayoutKind.Sequential)]
00023   internal struct DBusObjectPathVTable
00024   {
00025     public DBusObjectPathUnregisterFunction unregisterFunction;
00026     public DBusObjectPathMessageFunction messageFunction;
00027     public IntPtr padding1;
00028     public IntPtr padding2;
00029     public IntPtr padding3;
00030     public IntPtr padding4;
00031     
00032     public DBusObjectPathVTable(DBusObjectPathUnregisterFunction unregisterFunction,
00033                                 DBusObjectPathMessageFunction messageFunction) 
00034     {
00035       this.unregisterFunction = unregisterFunction;
00036       this.messageFunction = messageFunction;
00037       this.padding1 = IntPtr.Zero;
00038       this.padding2 = IntPtr.Zero;
00039       this.padding3 = IntPtr.Zero;
00040       this.padding4 = IntPtr.Zero;
00041     }
00042   }
00043 
00044   public class Connection : IDisposable
00045   {
00049     private IntPtr rawConnection;
00050     
00054     private static int slot = -1;
00055     
00056     private int timeout = -1;
00057 
00058     private ArrayList filters = new ArrayList ();      // of DBusHandleMessageFunction
00059     private ArrayList matches = new ArrayList ();      // of string
00060     private Hashtable object_paths = new Hashtable (); // key: string  value: DBusObjectPathVTable
00061 
00062     internal Connection(IntPtr rawConnection)
00063     {
00064       RawConnection = rawConnection;
00065       ExitOnDisconnect = true;
00066     }
00067     
00068     public Connection(string address)
00069     {
00070       // the assignment bumps the refcount
00071       Error error = new Error();
00072       error.Init();
00073       RawConnection = dbus_connection_open(address, ref error);
00074       if (RawConnection != IntPtr.Zero) {
00075         dbus_connection_unref(RawConnection);
00076       } else {
00077         throw new DBusException(error);
00078       }
00079 
00080       SetupWithMain();
00081       ExitOnDisconnect = true;
00082     }
00083 
00084     public void Dispose() 
00085     {
00086       Dispose(true);
00087       GC.SuppressFinalize(this);
00088     }
00089     
00090     public void Dispose (bool disposing) 
00091     {
00092       if (disposing && RawConnection != IntPtr.Zero) 
00093         {
00094           dbus_connection_disconnect(rawConnection);
00095 
00096           RawConnection = IntPtr.Zero; // free the native object
00097         }
00098     }
00099 
00100     public void Flush()
00101     {
00102       dbus_connection_flush(RawConnection);
00103     }
00104 
00105     public void SetupWithMain() 
00106     {      
00107       dbus_connection_setup_with_g_main(RawConnection, IntPtr.Zero);
00108     }
00109     
00110     ~Connection () 
00111     {
00112       Dispose (false);
00113     }
00114     
00115     internal static Connection Wrap(IntPtr rawConnection) 
00116     {
00117       if (slot > -1) {
00118         // Maybe we already have a Connection object associated with
00119         // this rawConnection then return it
00120         IntPtr rawThis = dbus_connection_get_data (rawConnection, slot);
00121         if (rawThis != IntPtr.Zero && ((GCHandle)rawThis).Target == typeof(DBus.Connection)) {
00122           return (DBus.Connection) ((GCHandle)rawThis).Target;
00123         }
00124       }
00125       
00126       // If it doesn't exist then create a new connection around it
00127       return new Connection(rawConnection);
00128     }
00129 
00130     public void AddFilter (DBusHandleMessageFunction func)
00131     {
00132       if (!dbus_connection_add_filter (RawConnection,
00133                                        func,
00134                                        IntPtr.Zero,
00135                                        IntPtr.Zero))
00136         throw new OutOfMemoryException ();
00137 
00138       this.filters.Add (func);
00139     }
00140 
00141     public void RemoveFilter (DBusHandleMessageFunction func)
00142     {
00143       dbus_connection_remove_filter (RawConnection, func, IntPtr.Zero);
00144 
00145       this.filters.Remove (func);
00146     }
00147 
00148     public void AddMatch (string match_rule)
00149     {
00150       dbus_bus_add_match (RawConnection, match_rule, IntPtr.Zero);
00151 
00152       this.matches.Add (match_rule);
00153     }
00154 
00155     public void RemoveMatch (string match_rule)
00156     {
00157       dbus_bus_remove_match (RawConnection, match_rule, IntPtr.Zero);
00158 
00159       this.matches.Remove (match_rule);
00160     }
00161 
00162     internal void RegisterObjectPath (string path, DBusObjectPathVTable vtable)
00163     {
00164       if (!dbus_connection_register_object_path (RawConnection, path, ref vtable, IntPtr.Zero))
00165         throw new OutOfMemoryException ();
00166  
00167       this.object_paths[path] = vtable;
00168     }
00169  
00170     internal void UnregisterObjectPath (string path)
00171     {
00172       dbus_connection_unregister_object_path (RawConnection, path);
00173  
00174       this.object_paths.Remove (path);
00175     }
00176 
00177 
00178     public string UniqueName
00179     {
00180       get
00181         {
00182           return Marshal.PtrToStringAnsi (dbus_bus_get_unique_name (RawConnection));
00183         }
00184     }
00185 
00186     public int Timeout
00187     {
00188       get
00189         {
00190           return this.timeout;
00191         }
00192       set
00193         {
00194           this.timeout = value;
00195         }
00196     }
00197 
00198     public bool ExitOnDisconnect
00199     {
00200       set
00201     {
00202       dbus_connection_set_exit_on_disconnect(RawConnection, value);
00203     }
00204     }
00205     
00206     private int Slot
00207     {
00208       get 
00209         {
00210           if (slot == -1) 
00211             {
00212               // We need to initialize the slot
00213               if (!dbus_connection_allocate_data_slot (ref slot))
00214                 throw new OutOfMemoryException ();
00215               
00216               Debug.Assert (slot >= 0);
00217             }
00218           
00219           return slot;
00220         }
00221     }
00222     
00223     internal IntPtr RawConnection 
00224     {
00225       get 
00226         {
00227           return rawConnection;
00228         }
00229       set 
00230         {
00231           if (value == rawConnection)
00232             return;
00233           
00234           if (rawConnection != IntPtr.Zero) 
00235             {
00236               // Remove our callbacks from this connection
00237               foreach (DBusHandleMessageFunction func in this.filters)
00238                 dbus_connection_remove_filter (rawConnection, func, IntPtr.Zero);
00239 
00240               foreach (string match_rule in this.matches)
00241                 dbus_bus_remove_match (rawConnection, match_rule, IntPtr.Zero);
00242 
00243               foreach (string path in this.object_paths.Keys)
00244                 dbus_connection_unregister_object_path (rawConnection, path);
00245 
00246               // Get the reference to this
00247               IntPtr rawThis = dbus_connection_get_data (rawConnection, Slot);
00248               Debug.Assert (rawThis != IntPtr.Zero);
00249               
00250               // Blank over the reference
00251               dbus_connection_set_data (rawConnection, Slot, IntPtr.Zero, IntPtr.Zero);
00252               
00253               // Free the reference
00254               ((GCHandle) rawThis).Free();
00255               
00256               // Unref the connection
00257               dbus_connection_unref(rawConnection);
00258             }
00259           
00260           this.rawConnection = value;
00261           
00262           if (rawConnection != IntPtr.Zero) 
00263             {
00264               GCHandle rawThis;
00265               
00266               dbus_connection_ref (rawConnection);
00267               
00268               // We store a weak reference to the C# object on the C object
00269               rawThis = GCHandle.Alloc (this, GCHandleType.WeakTrackResurrection);
00270               
00271               dbus_connection_set_data(rawConnection, Slot, (IntPtr) rawThis, IntPtr.Zero);
00272 
00273               // Add the callbacks to this new connection
00274               foreach (DBusHandleMessageFunction func in this.filters)
00275                 dbus_connection_add_filter (rawConnection, func, IntPtr.Zero, IntPtr.Zero);
00276 
00277               foreach (string match_rule in this.matches)
00278                 dbus_bus_add_match (rawConnection, match_rule, IntPtr.Zero);
00279 
00280               foreach (string path in this.object_paths.Keys) {
00281                 DBusObjectPathVTable vtable = (DBusObjectPathVTable) this.object_paths[path];
00282                 dbus_connection_register_object_path (rawConnection, path, ref vtable, IntPtr.Zero);
00283               }
00284             }
00285           else
00286             {
00287               this.filters.Clear ();
00288               this.matches.Clear ();
00289               this.object_paths.Clear ();
00290             }
00291         }
00292     }
00293 
00294     [DllImport("dbus-glib-1")]
00295     private extern static void dbus_connection_setup_with_g_main(IntPtr rawConnection,
00296                                                              IntPtr rawContext);
00297     
00298     [DllImport ("dbus-1")]
00299     private extern static IntPtr dbus_connection_open (string address, ref Error error);
00300     
00301     [DllImport ("dbus-1")]
00302     private extern static void dbus_connection_unref (IntPtr ptr);
00303     
00304     [DllImport ("dbus-1")]
00305     private extern static void dbus_connection_ref (IntPtr ptr);
00306     
00307     [DllImport ("dbus-1")]
00308     private extern static bool dbus_connection_allocate_data_slot (ref int slot);
00309     
00310     [DllImport ("dbus-1")]
00311     private extern static void dbus_connection_free_data_slot (ref int slot);
00312     
00313     [DllImport ("dbus-1")]
00314     private extern static bool dbus_connection_set_data (IntPtr ptr,
00315                                                          int    slot,
00316                                                          IntPtr data,
00317                                                          IntPtr free_data_func);
00318     
00319     [DllImport ("dbus-1")]
00320     private extern static void dbus_connection_flush (IntPtr  ptr);
00321     
00322     [DllImport ("dbus-1")]
00323     private extern static IntPtr dbus_connection_get_data (IntPtr ptr,
00324                                                            int    slot);
00325     
00326     [DllImport ("dbus-1")]
00327     private extern static void dbus_connection_disconnect (IntPtr ptr);
00328 
00329     [DllImport ("dbus-1")]
00330     private extern static IntPtr dbus_bus_get_unique_name (IntPtr ptr);
00331 
00332     [DllImport("dbus-1")]
00333     private extern static bool dbus_connection_add_filter(IntPtr rawConnection,
00334                                                           DBusHandleMessageFunction filter,
00335                                                           IntPtr userData,
00336                                                           IntPtr freeData);
00337 
00338     [DllImport("dbus-1")]
00339     private extern static void dbus_connection_remove_filter(IntPtr rawConnection,
00340                                                              DBusHandleMessageFunction filter,
00341                                                              IntPtr userData);
00342 
00343     [DllImport("dbus-1")]
00344     private extern static void dbus_bus_add_match(IntPtr rawConnection,
00345                                                   string rule,
00346                                                   IntPtr erro);
00347 
00348     [DllImport("dbus-1")]
00349     private extern static void dbus_bus_remove_match(IntPtr rawConnection,
00350                                                      string rule,
00351                                                      IntPtr erro);
00352 
00353     [DllImport ("dbus-1")]
00354     private extern static bool dbus_connection_register_object_path (IntPtr rawConnection,
00355                                                                      string path,
00356                                                                      ref DBusObjectPathVTable vTable,
00357                                                                      IntPtr userData);
00358 
00359     [DllImport ("dbus-1")]
00360     private extern static void dbus_connection_unregister_object_path (IntPtr rawConnection,
00361                                                                        string path);
00362 
00363     [DllImport ("dbus-1")]
00364     private extern static void dbus_connection_set_exit_on_disconnect (IntPtr rawConnection,
00365                           bool exitOnDisconnect);
00366   }
00367 }

Generated on Wed Feb 27 10:13:37 2008 for D-BUS by  doxygen 1.4.6