]> git.meshlink.io Git - catta/commitdiff
add initial mono bindings
authorJames Willcox <snopr@snorp.net>
Fri, 9 Sep 2005 17:12:57 +0000 (17:12 +0000)
committerJames Willcox <snopr@snorp.net>
Fri, 9 Sep 2005 17:12:57 +0000 (17:12 +0000)
git-svn-id: file:///home/lennart/svn/public/avahi/trunk@538 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe

13 files changed:
avahi-sharp/AddressResolver.cs [new file with mode: 0644]
avahi-sharp/AvahiTest.cs [new file with mode: 0644]
avahi-sharp/Client.cs [new file with mode: 0644]
avahi-sharp/ClientException.cs [new file with mode: 0644]
avahi-sharp/DomainBrowser.cs [new file with mode: 0644]
avahi-sharp/EntryGroup.cs [new file with mode: 0644]
avahi-sharp/HostNameResolver.cs [new file with mode: 0644]
avahi-sharp/Makefile.am [new file with mode: 0644]
avahi-sharp/ServiceBrowser.cs [new file with mode: 0644]
avahi-sharp/ServiceResolver.cs [new file with mode: 0644]
avahi-sharp/ServiceTypeBrowser.cs [new file with mode: 0644]
avahi-sharp/Utility.cs [new file with mode: 0644]
configure.ac

diff --git a/avahi-sharp/AddressResolver.cs b/avahi-sharp/AddressResolver.cs
new file mode 100644 (file)
index 0000000..730645f
--- /dev/null
@@ -0,0 +1,132 @@
+using System;
+using System.Collections;
+using System.Net;
+using System.Runtime.InteropServices;
+using Mono.Unix;
+
+namespace Avahi
+{
+
+    internal delegate void AddressResolverCallback (IntPtr resolver, int iface, Protocol proto,
+                                                    ResolverEvent revent, Protocol aproto, IntPtr address,
+                                                    IntPtr hostname, IntPtr userdata);
+
+    public delegate void HostAddressHandler (object o, string host, IPAddress address);
+    
+    public class AddressResolver : IDisposable
+    {
+        private IntPtr handle;
+        private Client client;
+        private int iface;
+        private Protocol proto;
+        private IPAddress address;
+
+        private IPAddress currentAddress;
+        private string currentHost;
+
+        private ArrayList foundListeners = new ArrayList ();
+        private ArrayList timeoutListeners = new ArrayList ();
+        
+        [DllImport ("avahi-client")]
+        private static extern IntPtr avahi_address_resolver_new (IntPtr client, int iface, Protocol proto,
+                                                                 IntPtr address, AddressResolverCallback cb,
+                                                                 IntPtr userdata);
+
+        [DllImport ("avahi-client")]
+        private static extern void avahi_address_resolver_free (IntPtr handle);
+
+        public event HostAddressHandler Found
+        {
+            add {
+                foundListeners.Add (value);
+                Start ();
+            }
+            remove {
+                foundListeners.Remove (value);
+                Stop (false);
+            }
+        }
+        
+        public event EventHandler Timeout
+        {
+            add {
+                timeoutListeners.Add (value);
+                Start ();
+            }
+            remove {
+                timeoutListeners.Remove (value);
+                Stop (false);
+            }
+        }
+
+        public IPAddress Address
+        {
+            get { return currentAddress; }
+        }
+
+        public string HostName
+        {
+            get { return currentHost; }
+        }
+
+        public AddressResolver (Client client, IPAddress address) : this (client, -1, Protocol.Unspecified, address)
+        {
+        }
+
+        public AddressResolver (Client client, int iface, Protocol proto, IPAddress address)
+        {
+            this.client = client;
+            this.iface = iface;
+            this.proto = proto;
+            this.address = address;
+        }
+
+        ~AddressResolver ()
+        {
+            Dispose ();
+        }
+
+        public void Dispose ()
+        {
+            Stop (true);
+        }
+
+        private void Start ()
+        {
+            if (handle != IntPtr.Zero || (foundListeners.Count == 0 && timeoutListeners.Count == 0))
+                return;
+
+            IntPtr addrPtr = Utility.StringToPtr (address.ToString ());
+            handle = avahi_address_resolver_new (client.Handle, iface, proto, addrPtr,
+                                                 OnAddressResolverCallback, IntPtr.Zero);
+            Utility.Free (addrPtr);
+        }
+
+        private void Stop (bool force)
+        {
+            if (handle != IntPtr.Zero && (force || (foundListeners.Count == 0 && timeoutListeners.Count == 0))) {
+                avahi_address_resolver_free (handle);
+                handle = IntPtr.Zero;
+            }
+        }
+
+        private void OnAddressResolverCallback (IntPtr resolver, int iface, Protocol proto,
+                                                ResolverEvent revent, Protocol aproto, IntPtr address,
+                                                IntPtr hostname, IntPtr userdata)
+        {
+            if (revent == ResolverEvent.Found) {
+                currentAddress = Utility.PtrToAddress (address);
+                currentHost = Utility.PtrToString (hostname);
+
+                foreach (HostAddressHandler handler in foundListeners)
+                    handler (this, currentHost, currentAddress);
+            } else {
+                currentAddress = null;
+                currentHost = null;
+                
+                foreach (EventHandler handler in timeoutListeners)
+                    handler (this, new EventArgs ());
+            }
+        }
+    }
+}
diff --git a/avahi-sharp/AvahiTest.cs b/avahi-sharp/AvahiTest.cs
new file mode 100644 (file)
index 0000000..0507204
--- /dev/null
@@ -0,0 +1,70 @@
+using System;
+using System.Net;
+using Gtk;
+using Avahi;
+
+public class AvahiTest {
+       private static Client client;
+
+       public static void Main () {
+               client = new Client ();
+
+               EntryGroup eg = new EntryGroup (client);
+               eg.StateChanged += OnEntryGroupChanged;
+               eg.AddService ("foobar2", "_daap._tcp", client.DomainName,
+                              444, new string[] { "foo", "bar", "baz" });
+               eg.Commit ();
+
+               Application.Run ();
+       }
+
+       private static void OnEntryGroupChanged (object o, EntryGroupState state)
+       {
+               Console.WriteLine ("Entry group status: " + state);
+
+               if (state == EntryGroupState.Established) {
+                       DomainBrowser browser = new DomainBrowser (client);
+                       browser.DomainAdded += OnDomainAdded;
+               }
+       }
+
+       private static void OnDomainAdded (object o, DomainInfo info)
+       {
+               Console.WriteLine ("Got domain added: " + info.Domain);
+               ServiceTypeBrowser stb = new ServiceTypeBrowser (client, info.Domain);
+               stb.ServiceTypeAdded += OnServiceTypeAdded;
+       }
+
+       private static void OnServiceTypeAdded (object o, ServiceTypeInfo info)
+       {
+               Console.WriteLine ("Got service type: " + info.ServiceType);
+               ServiceBrowser sb = new ServiceBrowser (client, info.ServiceType, info.Domain);
+               sb.ServiceAdded += OnServiceAdded;
+       }
+
+       private static void OnServiceAdded (object o, ServiceInfo info)
+       {
+               // Console.WriteLine ("Got service: " + info.Name);
+               ServiceResolver resolver = new ServiceResolver (client, info);
+               resolver.Found += OnServiceResolved;
+       }
+
+       private static void OnServiceResolved (object o, ServiceInfo info)
+       {
+               Console.WriteLine ("Service '{0}' at {1}:{2}", info.Name, info.Host, info.Port);
+               AddressResolver ar = new AddressResolver (client, info.Address);
+               ar.Found += OnAddressResolved;
+       }
+
+       private static void OnAddressResolved (object o, string host, IPAddress address)
+       {
+               Console.WriteLine ("Resolved {0} to {1}", address, host);
+               HostNameResolver hr = new HostNameResolver (client, host);
+               hr.Found += OnHostNameResolved;
+       }
+
+       private static void OnHostNameResolved (object o, string host, IPAddress address)
+       {
+               Console.WriteLine ("Resolved {0} to {1}", host, address);
+       }
+}
diff --git a/avahi-sharp/Client.cs b/avahi-sharp/Client.cs
new file mode 100644 (file)
index 0000000..99651cd
--- /dev/null
@@ -0,0 +1,141 @@
+
+using System;
+using System.Collections;
+using System.Runtime.InteropServices;
+
+namespace Avahi
+{
+    internal enum ResolverEvent {
+        Found,
+        Timeout
+    }
+    
+    internal enum BrowserEvent {
+        Added,
+        Removed
+    }
+    
+    internal delegate void ClientHandler (IntPtr client, ClientState state, IntPtr userData);
+
+    public enum Protocol {
+        Unspecified = 0,
+        IPv4 = 2,
+        IPv6 = 10
+    }
+    
+    public enum ClientState {
+        Invalid,
+        Registering,
+        Running,
+        Collision,
+        Disconnected = 100
+    }
+    
+    public class Client : IDisposable
+    {
+        private IntPtr handle;
+
+        [DllImport ("avahi-client")]
+        private static extern IntPtr avahi_client_new (IntPtr poll, ClientHandler handler,
+                                                       IntPtr userData, out int error);
+
+        [DllImport ("avahi-client")]
+        private static extern void avahi_client_free (IntPtr handle);
+
+        [DllImport ("avahi-client")]
+        private static extern IntPtr avahi_client_get_version_string (IntPtr handle);
+
+        [DllImport ("avahi-client")]
+        private static extern IntPtr avahi_client_get_host_name (IntPtr handle);
+
+        [DllImport ("avahi-client")]
+        private static extern IntPtr avahi_client_get_domain_name (IntPtr handle);
+
+        [DllImport ("avahi-client")]
+        private static extern IntPtr avahi_client_get_host_name_fqdn (IntPtr handle);
+
+        [DllImport ("avahi-client")]
+        private static extern ClientState avahi_client_get_state (IntPtr handle);
+
+        [DllImport ("avahi-client")]
+        private static extern int avahi_client_errno (IntPtr handle);
+        
+        [DllImport ("avahi-glib")]
+        private static extern IntPtr avahi_glib_poll_new (IntPtr context, int priority);
+
+        [DllImport ("avahi-glib")]
+        private static extern IntPtr avahi_glib_poll_get (IntPtr gpoll);
+
+        internal IntPtr Handle
+        {
+            get { return handle; }
+        }
+        
+        public string Version
+        {
+            get { return Utility.PtrToString (avahi_client_get_version_string (handle)); }
+        }
+
+        public string HostName
+        {
+            get { return Utility.PtrToString (avahi_client_get_host_name (handle)); }
+        }
+
+        public string DomainName
+        {
+            get { return Utility.PtrToString (avahi_client_get_domain_name (handle)); }
+        }
+
+        public string HostNameFqdn
+        {
+            get { return Utility.PtrToString (avahi_client_get_host_name_fqdn (handle)); }
+        }
+
+        public ClientState State
+        {
+            get { return (ClientState) avahi_client_get_state (handle); }
+        }
+
+        internal int LastError
+        {
+            get { return avahi_client_errno (handle); }
+        }
+
+        public Client ()
+        {
+            IntPtr gpoll = avahi_glib_poll_new (IntPtr.Zero, 0);
+            IntPtr poll = avahi_glib_poll_get (gpoll);
+
+            int error;
+            handle = avahi_client_new (poll, OnClientCallback, IntPtr.Zero, out error);
+            if (error != 0)
+                throw new ClientException (error);
+        }
+
+        ~Client ()
+        {
+            Dispose ();
+        }
+
+        public void Dispose ()
+        {
+            if (handle != IntPtr.Zero) {
+                avahi_client_free (handle);
+                handle = IntPtr.Zero;
+            }
+        }
+
+        internal void CheckError ()
+        {
+            int error = LastError;
+
+            if (error != 0)
+                throw new ClientException (error);
+        }
+        
+        private void OnClientCallback (IntPtr client, ClientState state, IntPtr userData)
+        {
+            Console.WriteLine ("Got new state: " + state);
+        }
+    }
+}
diff --git a/avahi-sharp/ClientException.cs b/avahi-sharp/ClientException.cs
new file mode 100644 (file)
index 0000000..f38f438
--- /dev/null
@@ -0,0 +1,30 @@
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace Avahi
+{
+    public class ClientException : ApplicationException
+    {
+        private int code;
+
+        [DllImport ("avahi-common")]
+        private static extern IntPtr avahi_strerror (int code);
+        
+        public int ErrorCode
+        {
+            get { return code; }
+        }
+        
+        internal ClientException (int code) : base (GetErrorString (code))
+        {
+            this.code = code;
+        }
+
+        private static string GetErrorString (int code)
+        {
+            IntPtr str = avahi_strerror (code);
+            return Utility.PtrToString (str);
+        }
+    }
+}
diff --git a/avahi-sharp/DomainBrowser.cs b/avahi-sharp/DomainBrowser.cs
new file mode 100644 (file)
index 0000000..deed9b8
--- /dev/null
@@ -0,0 +1,143 @@
+using System;
+using System.Collections;
+using System.Runtime.InteropServices;
+
+namespace Avahi
+{
+    internal delegate void DomainBrowserCallback (IntPtr browser, int iface, Protocol proto, BrowserEvent bevent,
+                                                  IntPtr domain, IntPtr userdata);
+
+    public enum DomainBrowserType {
+        Register,
+        RegisterDefault,
+        Browse,
+        BrowseDefault,
+        BrowseLegacy
+    }
+
+    public struct DomainInfo
+    {
+        public int NetworkInterface;
+        public Protocol Protocol;
+        public string Domain;
+    }
+
+    public delegate void DomainInfoHandler (object o, DomainInfo info);
+    
+    public class DomainBrowser : IDisposable
+    {
+        private IntPtr handle;
+        private ArrayList infos = new ArrayList ();
+        private Client client;
+        private int iface;
+        private Protocol proto;
+        private string domain;
+        private DomainBrowserType btype;
+
+        private ArrayList addListeners = new ArrayList ();
+        private ArrayList removeListeners = new ArrayList ();
+        
+        [DllImport ("avahi-client")]
+        private static extern IntPtr avahi_domain_browser_new (IntPtr client, int iface, int proto,
+                                                               IntPtr domain, int btype, DomainBrowserCallback cb,
+                                                               IntPtr userdata);
+
+        [DllImport ("avahi-client")]
+        private static extern void avahi_domain_browser_free (IntPtr handle);
+
+        public event DomainInfoHandler DomainAdded
+        {
+            add {
+                addListeners.Add (value);
+                Start ();
+            }
+            remove {
+                addListeners.Remove (value);
+                Stop (false);
+            }
+        }
+        
+        public event DomainInfoHandler DomainRemoved
+        {
+            add {
+                removeListeners.Add (value);
+                Start ();
+            }
+            remove {
+                removeListeners.Remove (value);
+                Stop (false);
+            }
+        }
+
+        public DomainInfo[] Domains
+        {
+            get { return (DomainInfo[]) infos.ToArray (typeof (DomainInfo)); }
+        }
+
+        public DomainBrowser (Client client) : this (client, -1, Protocol.Unspecified, client.DomainName,
+                                                     DomainBrowserType.Browse) {
+        }
+        
+        public DomainBrowser (Client client, int iface, Protocol proto, string domain, DomainBrowserType btype)
+        {
+            this.client = client;
+            this.iface = iface;
+            this.proto = proto;
+            this.domain = domain;
+            this.btype = btype;
+        }
+
+        ~DomainBrowser ()
+        {
+            Dispose ();
+        }
+
+        public void Dispose ()
+        {
+            Stop (true);
+        }
+
+        private void Start ()
+        {
+            if (handle != IntPtr.Zero || (addListeners.Count == 0 && removeListeners.Count == 0))
+                return;
+
+            IntPtr domainPtr = Utility.StringToPtr (domain);
+            handle = avahi_domain_browser_new (client.Handle, iface, (int) proto, domainPtr, (int) btype,
+                                               OnDomainBrowserCallback, IntPtr.Zero);
+            Utility.Free (domainPtr);
+        }
+
+        private void Stop (bool force)
+        {
+            if (handle != IntPtr.Zero && (force || (addListeners.Count == 0 && removeListeners.Count == 0))) {
+                avahi_domain_browser_free (handle);
+                handle = IntPtr.Zero;
+            }
+        }
+
+        private void OnDomainBrowserCallback (IntPtr browser, int iface, Protocol proto, BrowserEvent bevent,
+                                              IntPtr domain, IntPtr userdata)
+        {
+
+            DomainInfo info;
+            info.NetworkInterface = iface;
+            info.Protocol = proto;
+            info.Domain = Utility.PtrToString (domain);
+
+            infos.Add (info);
+            
+            if (bevent == BrowserEvent.Added) {
+                infos.Add (info);
+
+                foreach (DomainInfoHandler handler in addListeners)
+                    handler (this, info);
+            } else {
+                infos.Remove (info);
+
+                foreach (DomainInfoHandler handler in removeListeners)
+                    handler (this, info);
+            }
+        }
+    }
+}
diff --git a/avahi-sharp/EntryGroup.cs b/avahi-sharp/EntryGroup.cs
new file mode 100644 (file)
index 0000000..74a127c
--- /dev/null
@@ -0,0 +1,137 @@
+using System;
+using System.Runtime.InteropServices;
+
+
+namespace Avahi
+{
+
+    public enum EntryGroupState {
+        Uncommited,
+        Registering,
+        Established,
+        Collision
+    }
+
+    internal delegate void EntryGroupCallback (IntPtr group, EntryGroupState state, IntPtr userdata);
+    public delegate void EntryGroupStateHandler (object o, EntryGroupState state);
+    
+    public class EntryGroup : IDisposable
+    {
+        private Client client;
+        private IntPtr handle;
+        
+        [DllImport ("avahi-client")]
+        private static extern IntPtr avahi_entry_group_new (IntPtr client, EntryGroupCallback cb, IntPtr userdata);
+
+        [DllImport ("avahi-client")]
+        private static extern void avahi_entry_group_commit (IntPtr group);
+
+        [DllImport ("avahi-client")]
+        private static extern void avahi_entry_group_reset (IntPtr group);
+
+        [DllImport ("avahi-client")]
+        private static extern EntryGroupState avahi_entry_group_get_state (IntPtr group);
+
+        [DllImport ("avahi-client")]
+        private static extern bool avahi_entry_group_is_empty (IntPtr group);
+
+        [DllImport ("avahi-client")]
+        private static extern void avahi_entry_group_add_service_strlst (IntPtr group, int iface, Protocol proto,
+                                                                         IntPtr name, IntPtr type, IntPtr domain,
+                                                                         IntPtr host, UInt16 port, IntPtr strlst);
+        
+        [DllImport ("avahi-client")]
+        private static extern void avahi_entry_group_free (IntPtr group);
+
+        [DllImport ("avahi-common")]
+        private static extern IntPtr avahi_string_list_new (IntPtr txt);
+
+        [DllImport ("avahi-common")]
+        private static extern void avahi_string_list_add (IntPtr list, IntPtr txt);
+
+        [DllImport ("avahi-common")]
+        private static extern void avahi_string_list_free (IntPtr list);
+
+        public event EntryGroupStateHandler StateChanged;
+        
+        public EntryGroupState State
+        {
+            get { return avahi_entry_group_get_state (handle); }
+        }
+
+        public bool IsEmpty
+        {
+            get { return avahi_entry_group_is_empty (handle); }
+        }
+        
+        public EntryGroup (Client client)
+        {
+            this.client = client;
+            handle = avahi_entry_group_new (client.Handle, OnEntryGroupCallback, IntPtr.Zero);
+            client.CheckError ();
+        }
+
+        ~EntryGroup ()
+        {
+            Dispose ();
+        }
+
+        public void Dispose ()
+        {
+            if (handle != IntPtr.Zero) {
+                avahi_entry_group_free (handle);
+                handle = IntPtr.Zero;
+            }
+        }
+
+        public void Commit ()
+        {
+            avahi_entry_group_commit (handle);
+            client.CheckError ();
+        }
+
+        public void Reset ()
+        {
+            avahi_entry_group_reset (handle);
+            client.CheckError ();
+        }
+
+        public void AddService (string name, string type, string domain,
+                                UInt16 port, string[] txt)
+        {
+            AddService (-1, Protocol.Unspecified, name, type, domain, null, port, txt);
+        }
+
+        public void AddService (int iface, Protocol proto, string name, string type, string domain,
+                                string host, UInt16 port, string[] txt)
+        {
+            IntPtr list = avahi_string_list_new (IntPtr.Zero);
+
+            if (txt != null) {
+                foreach (string item in txt) {
+                    IntPtr itemPtr = Utility.StringToPtr (item);
+                    avahi_string_list_add (list, itemPtr);
+                    Utility.Free (itemPtr);
+                }
+            }
+
+            IntPtr namePtr = Utility.StringToPtr (name);
+            IntPtr typePtr = Utility.StringToPtr (type);
+            IntPtr domainPtr = Utility.StringToPtr (domain);
+            IntPtr hostPtr = Utility.StringToPtr (host);
+            avahi_entry_group_add_service_strlst (handle, iface, proto, namePtr, typePtr, domainPtr,
+                                                  hostPtr, port, list);
+            avahi_string_list_free (list);
+
+            client.CheckError ();
+            
+            Console.WriteLine ("Added service: {0}, {1}, {2}, {3}, {4}", name, type, domain, host, port);
+        }
+
+        private void OnEntryGroupCallback (IntPtr group, EntryGroupState state, IntPtr userdata)
+        {
+            if (StateChanged != null)
+                StateChanged (this, state);
+        }
+    }
+}
diff --git a/avahi-sharp/HostNameResolver.cs b/avahi-sharp/HostNameResolver.cs
new file mode 100644 (file)
index 0000000..62f4149
--- /dev/null
@@ -0,0 +1,134 @@
+using System;
+using System.Collections;
+using System.Net;
+using System.Runtime.InteropServices;
+using Mono.Unix;
+
+namespace Avahi
+{
+
+    internal delegate void HostNameResolverCallback (IntPtr resolver, int iface, Protocol proto,
+                                                     ResolverEvent revent, IntPtr hostname, IntPtr address,
+                                                     IntPtr userdata);
+
+    public class HostNameResolver : IDisposable
+    {
+        private IntPtr handle;
+        private Client client;
+        private int iface;
+        private Protocol proto;
+        private string hostname;
+        private Protocol aproto;
+
+        private IPAddress currentAddress;
+        private string currentHost;
+
+        private ArrayList foundListeners = new ArrayList ();
+        private ArrayList timeoutListeners = new ArrayList ();
+        
+        [DllImport ("avahi-client")]
+        private static extern IntPtr avahi_host_name_resolver_new (IntPtr client, int iface, Protocol proto,
+                                                                   IntPtr hostname, Protocol aproto,
+                                                                   HostNameResolverCallback cb, IntPtr userdata);
+
+        [DllImport ("avahi-client")]
+        private static extern void avahi_host_name_resolver_free (IntPtr handle);
+
+        public event HostAddressHandler Found
+        {
+            add {
+                foundListeners.Add (value);
+                Start ();
+            }
+            remove {
+                foundListeners.Remove (value);
+                Stop (false);
+            }
+        }
+        
+        public event EventHandler Timeout
+        {
+            add {
+                timeoutListeners.Add (value);
+                Start ();
+            }
+            remove {
+                timeoutListeners.Remove (value);
+                Stop (false);
+            }
+        }
+
+        public IPAddress Address
+        {
+            get { return currentAddress; }
+        }
+
+        public string HostName
+        {
+            get { return currentHost; }
+        }
+
+        public HostNameResolver (Client client, string hostname) : this (client, -1, Protocol.Unspecified,
+                                                                         hostname, Protocol.Unspecified)
+        {
+        }
+
+        public HostNameResolver (Client client, int iface, Protocol proto, string hostname,
+                                 Protocol aproto)
+        {
+            this.client = client;
+            this.iface = iface;
+            this.proto = proto;
+            this.hostname = hostname;
+            this.aproto = aproto;
+        }
+
+        ~HostNameResolver ()
+        {
+            Dispose ();
+        }
+
+        public void Dispose ()
+        {
+            Stop (true);
+        }
+
+        private void Start ()
+        {
+            if (handle != IntPtr.Zero || (foundListeners.Count == 0 && timeoutListeners.Count == 0))
+                return;
+
+            IntPtr hostPtr = Utility.StringToPtr (hostname);
+            handle = avahi_host_name_resolver_new (client.Handle, iface, proto, hostPtr, aproto,
+                                                   OnHostNameResolverCallback, IntPtr.Zero);
+            Utility.Free (hostPtr);
+        }
+
+        private void Stop (bool force)
+        {
+            if (handle != IntPtr.Zero && (force || (foundListeners.Count == 0 && timeoutListeners.Count == 0))) {
+                avahi_host_name_resolver_free (handle);
+                handle = IntPtr.Zero;
+            }
+        }
+
+        private void OnHostNameResolverCallback (IntPtr resolver, int iface, Protocol proto,
+                                                 ResolverEvent revent, IntPtr hostname, IntPtr address,
+                                                 IntPtr userdata)
+        {
+            if (revent == ResolverEvent.Found) {
+                currentAddress = Utility.PtrToAddress (address);
+                currentHost = Utility.PtrToString (hostname);
+
+                foreach (HostAddressHandler handler in foundListeners)
+                    handler (this, currentHost, currentAddress);
+            } else {
+                currentAddress = null;
+                currentHost = null;
+                
+                foreach (EventHandler handler in timeoutListeners)
+                    handler (this, new EventArgs ());
+            }
+        }
+    }
+}
diff --git a/avahi-sharp/Makefile.am b/avahi-sharp/Makefile.am
new file mode 100644 (file)
index 0000000..a82f4e6
--- /dev/null
@@ -0,0 +1,20 @@
+
+
+all: avahi-sharp.dll
+
+AVAHISOURCES =                                 \
+       $(srcdir)/AddressResolver.cs    \
+       $(srcdir)/Client.cs             \
+       $(srcdir)/ClientException.cs    \
+       $(srcdir)/DomainBrowser.cs      \
+       $(srcdir)/EntryGroup.cs         \
+       $(srcdir)/HostNameResolver.cs   \
+       $(srcdir)/ServiceBrowser.cs     \
+       $(srcdir)/ServiceResolver.cs    \
+       $(srcdir)/ServiceTypeBrowser.cs \
+       Utility.cs
+
+avahi-sharp.dll: $(AVAHISOURCES)
+       mcs -target:library -o $@ -debug $(AVAHISOURCES) -r:Mono.Posix
+
+CLEANFILES = avahi-sharp.dll avahi-sharp.dll.mdb
diff --git a/avahi-sharp/ServiceBrowser.cs b/avahi-sharp/ServiceBrowser.cs
new file mode 100644 (file)
index 0000000..975746b
--- /dev/null
@@ -0,0 +1,160 @@
+using System;
+using System.Net;
+using System.Collections;
+using System.Runtime.InteropServices;
+
+namespace Avahi
+{
+    internal delegate void ServiceBrowserCallback (IntPtr browser, int iface, Protocol proto, BrowserEvent bevent,
+                                                   IntPtr name, IntPtr type, IntPtr domain, IntPtr userdata);
+    
+    public struct ServiceInfo
+    {
+        public int NetworkInterface;
+        public Protocol Protocol;
+        public string Domain;
+        public string ServiceType;
+        public string Name;
+
+        public string Host;
+        public IPAddress Address;
+        public UInt16 Port;
+        public byte[][] Text;
+
+        public static ServiceInfo Zero = new ServiceInfo ();
+    }
+
+    public delegate void ServiceInfoHandler (object o, ServiceInfo info);
+    
+    public class ServiceBrowser : IDisposable
+    {
+        private IntPtr handle;
+        private ArrayList infos = new ArrayList ();
+        private Client client;
+        private int iface;
+        private Protocol proto;
+        private string domain;
+        private string type;
+
+        private ArrayList addListeners = new ArrayList ();
+        private ArrayList removeListeners = new ArrayList ();
+        
+        [DllImport ("avahi-client")]
+        private static extern IntPtr avahi_service_browser_new (IntPtr client, int iface, int proto, IntPtr type,
+                                                                IntPtr domain, ServiceBrowserCallback cb,
+                                                                IntPtr userdata);
+
+        [DllImport ("avahi-client")]
+        private static extern void avahi_service_browser_free (IntPtr handle);
+
+        public event ServiceInfoHandler ServiceAdded
+        {
+            add {
+                addListeners.Add (value);
+                Start ();
+            }
+            remove {
+                addListeners.Remove (value);
+                Stop (false);
+            }
+        }
+        
+        public event ServiceInfoHandler ServiceRemoved
+        {
+            add {
+                removeListeners.Add (value);
+                Start ();
+            }
+            remove {
+                removeListeners.Remove (value);
+                Stop (false);
+            }
+        }
+
+        public ServiceInfo[] Services
+        {
+            get { return (ServiceInfo[]) infos.ToArray (typeof (ServiceInfo)); }
+        }
+
+        public ServiceBrowser (Client client, string type) : this (client, type, client.DomainName)
+        {
+        }
+        
+        public ServiceBrowser (Client client, string type, string domain) : this (client, -1, Protocol.Unspecified,
+                                                                                  type, domain)
+        {
+        }
+        
+        public ServiceBrowser (Client client, int iface, Protocol proto, string type, string domain)
+        {
+            this.client = client;
+            this.iface = iface;
+            this.proto = proto;
+            this.domain = domain;
+            this.type = type;
+            
+            
+        }
+
+        ~ServiceBrowser ()
+        {
+            Dispose ();
+        }
+
+        public void Dispose ()
+        {
+            Stop (true);
+        }
+
+        private void Start ()
+        {
+            if (handle != IntPtr.Zero || (addListeners.Count == 0 && removeListeners.Count == 0))
+                return;
+
+            IntPtr domainPtr = Utility.StringToPtr (domain);
+            IntPtr typePtr = Utility.StringToPtr (type);
+            handle = avahi_service_browser_new (client.Handle, iface, (int) proto, typePtr, domainPtr,
+                                                OnServiceBrowserCallback, IntPtr.Zero);
+            Utility.Free (domainPtr);
+            Utility.Free (typePtr);
+        }
+
+        private void Stop (bool force)
+        {
+            if (handle != IntPtr.Zero && (force || (addListeners.Count == 0 && removeListeners.Count == 0))) {
+                avahi_service_browser_free (handle);
+                handle = IntPtr.Zero;
+            }
+        }
+
+        private void OnServiceBrowserCallback (IntPtr browser, int iface, Protocol proto, BrowserEvent bevent,
+                                               IntPtr name, IntPtr type, IntPtr domain, IntPtr userdata)
+        {
+
+            ServiceInfo info;
+            info.NetworkInterface = iface;
+            info.Protocol = proto;
+            info.Domain = Utility.PtrToString (domain);
+            info.ServiceType = Utility.PtrToString (type);
+            info.Name = Utility.PtrToString (name);
+            info.Host = null;
+            info.Address = null;
+            info.Port = 0;
+            info.Text = null;
+
+            infos.Add (info);
+            
+            if (bevent == BrowserEvent.Added) {
+                infos.Add (info);
+
+                foreach (ServiceInfoHandler handler in addListeners)
+                    handler (this, info);
+            } else {
+                infos.Remove (info);
+
+                foreach (ServiceInfoHandler handler in removeListeners)
+                    handler (this, info);
+            }
+        }
+    }
+}
diff --git a/avahi-sharp/ServiceResolver.cs b/avahi-sharp/ServiceResolver.cs
new file mode 100644 (file)
index 0000000..af3bf5b
--- /dev/null
@@ -0,0 +1,158 @@
+using System;
+using System.Collections;
+using System.Net;
+using System.Runtime.InteropServices;
+using Mono.Unix;
+
+namespace Avahi
+{
+
+    internal delegate void ServiceResolverCallback (IntPtr resolver, int iface, Protocol proto,
+                                                    ResolverEvent revent, IntPtr name, IntPtr type,
+                                                    IntPtr domain, IntPtr host, IntPtr address,
+                                                    UInt16 port, IntPtr txt, IntPtr userdata);
+
+    public class ServiceResolver : IDisposable
+    {
+        private IntPtr handle;
+        private ServiceInfo currentInfo;
+        private Client client;
+        private int iface;
+        private Protocol proto;
+        private string name;
+        private string type;
+        private string domain;
+        private Protocol aproto;
+
+        private ArrayList foundListeners = new ArrayList ();
+        private ArrayList timeoutListeners = new ArrayList ();
+        
+        [DllImport ("avahi-client")]
+        private static extern IntPtr avahi_service_resolver_new (IntPtr client, int iface, Protocol proto,
+                                                                 IntPtr name, IntPtr type, IntPtr domain,
+                                                                 Protocol aproto, ServiceResolverCallback cb,
+                                                                 IntPtr userdata);
+
+        [DllImport ("avahi-client")]
+        private static extern void avahi_service_resolver_free (IntPtr handle);
+
+        public event ServiceInfoHandler Found
+        {
+            add {
+                foundListeners.Add (value);
+                Start ();
+            }
+            remove {
+                foundListeners.Remove (value);
+                Stop (false);
+            }
+        }
+        
+        public event EventHandler Timeout
+        {
+            add {
+                timeoutListeners.Add (value);
+                Start ();
+            }
+            remove {
+                timeoutListeners.Remove (value);
+                Stop (false);
+            }
+        }
+
+        public ServiceInfo Service
+        {
+            get { return currentInfo; }
+        }
+
+        public ServiceResolver (Client client, string name, string type, string domain) : this (client, -1,
+                                                                                                Protocol.Unspecified,
+                                                                                                name, type, domain,
+                                                                                                Protocol.Unspecified)
+        {
+        }
+
+        public ServiceResolver (Client client, ServiceInfo service) : this (client, service.NetworkInterface,
+                                                                            service.Protocol, service.Name,
+                                                                            service.ServiceType, service.Domain,
+                                                                            Protocol.Unspecified)
+        {
+        }
+        
+        public ServiceResolver (Client client, int iface, Protocol proto, string name,
+                                string type, string domain, Protocol aproto)
+        {
+            this.client = client;
+            this.iface = iface;
+            this.proto = proto;
+            this.name = name;
+            this.type = type;
+            this.domain = domain;
+            this.aproto = aproto;
+            
+            
+        }
+
+        ~ServiceResolver ()
+        {
+            Dispose ();
+        }
+
+        public void Dispose ()
+        {
+            Stop (true);
+        }
+
+        private void Start ()
+        {
+            if (handle != IntPtr.Zero || (foundListeners.Count == 0 && timeoutListeners.Count == 0))
+                return;
+
+            IntPtr namePtr = Utility.StringToPtr (name);
+            IntPtr typePtr = Utility.StringToPtr (type);
+            IntPtr domainPtr = Utility.StringToPtr (domain);
+            handle = avahi_service_resolver_new (client.Handle, iface, proto, namePtr, typePtr, domainPtr,
+                                                 aproto, OnServiceResolverCallback, IntPtr.Zero);
+            Utility.Free (namePtr);
+            Utility.Free (typePtr);
+            Utility.Free (domainPtr);
+        }
+
+        private void Stop (bool force)
+        {
+            if (handle != IntPtr.Zero && (force || (foundListeners.Count == 0 && timeoutListeners.Count == 0))) {
+                avahi_service_resolver_free (handle);
+                handle = IntPtr.Zero;
+            }
+        }
+
+        private void OnServiceResolverCallback (IntPtr resolver, int iface, Protocol proto,
+                                                ResolverEvent revent, IntPtr name, IntPtr type,
+                                                IntPtr domain, IntPtr host, IntPtr address,
+                                                UInt16 port, IntPtr txt, IntPtr userdata)
+        {
+            ServiceInfo info;
+            info.NetworkInterface = iface;
+            info.Protocol = proto;
+            info.Domain = Utility.PtrToString (domain);
+            info.ServiceType = Utility.PtrToString (type);
+            info.Name = Utility.PtrToString (name);
+            info.Host = Utility.PtrToString (host);
+            info.Address = Utility.PtrToAddress (address);
+            info.Port = port;
+            info.Text = null;
+
+            if (revent == ResolverEvent.Found) {
+                currentInfo = info;
+
+                foreach (ServiceInfoHandler handler in foundListeners)
+                    handler (this, info);
+            } else {
+                currentInfo = ServiceInfo.Zero;
+                
+                foreach (EventHandler handler in timeoutListeners)
+                    handler (this, new EventArgs ());
+            }
+        }
+    }
+}
diff --git a/avahi-sharp/ServiceTypeBrowser.cs b/avahi-sharp/ServiceTypeBrowser.cs
new file mode 100644 (file)
index 0000000..0334b96
--- /dev/null
@@ -0,0 +1,139 @@
+using System;
+using System.Collections;
+using System.Runtime.InteropServices;
+
+namespace Avahi
+{
+    internal delegate void ServiceTypeBrowserCallback (IntPtr browser, int iface, Protocol proto, BrowserEvent bevent,
+                                                       IntPtr type, IntPtr domain, IntPtr userdata);
+    
+    public struct ServiceTypeInfo
+    {
+        public int NetworkInterface;
+        public Protocol Protocol;
+        public string Domain;
+        public string ServiceType;
+    }
+
+    public delegate void ServiceTypeInfoHandler (object o, ServiceTypeInfo info);
+    
+    public class ServiceTypeBrowser : IDisposable
+    {
+        private IntPtr handle;
+        private ArrayList infos = new ArrayList ();
+        private Client client;
+        private int iface;
+        private Protocol proto;
+        private string domain;
+
+        private ArrayList addListeners = new ArrayList ();
+        private ArrayList removeListeners = new ArrayList ();
+        
+        [DllImport ("avahi-client")]
+        private static extern IntPtr avahi_service_type_browser_new (IntPtr client, int iface, int proto,
+                                                                     IntPtr domain, ServiceTypeBrowserCallback cb,
+                                                                     IntPtr userdata);
+
+        [DllImport ("avahi-client")]
+        private static extern void avahi_service_type_browser_free (IntPtr handle);
+
+        public event ServiceTypeInfoHandler ServiceTypeAdded
+        {
+            add {
+                addListeners.Add (value);
+                Start ();
+            }
+            remove {
+                addListeners.Remove (value);
+                Stop (false);
+            }
+        }
+        
+        public event ServiceTypeInfoHandler ServiceTypeRemoved
+        {
+            add {
+                removeListeners.Add (value);
+                Start ();
+            }
+            remove {
+                removeListeners.Remove (value);
+                Stop (false);
+            }
+        }
+
+        public ServiceTypeInfo[] ServiceTypes
+        {
+            get { return (ServiceTypeInfo[]) infos.ToArray (typeof (ServiceTypeInfo)); }
+        }
+
+        public ServiceTypeBrowser (Client client) : this (client, client.DomainName)
+        {
+        }
+
+        public ServiceTypeBrowser (Client client, string domain) : this (client, -1, Protocol.Unspecified, domain)
+        {
+        }
+        
+        public ServiceTypeBrowser (Client client, int iface, Protocol proto, string domain)
+        {
+            this.client = client;
+            this.iface = iface;
+            this.proto = proto;
+            this.domain = domain;
+        }
+
+        ~ServiceTypeBrowser ()
+        {
+            Dispose ();
+        }
+
+        public void Dispose ()
+        {
+            Stop (true);
+        }
+
+        private void Start ()
+        {
+            if (handle != IntPtr.Zero || (addListeners.Count == 0 && removeListeners.Count == 0))
+                return;
+
+            IntPtr domainPtr = Utility.StringToPtr (domain);
+            handle = avahi_service_type_browser_new (client.Handle, iface, (int) proto, domainPtr,
+                                                     OnServiceTypeBrowserCallback, IntPtr.Zero);
+            Utility.Free (domainPtr);
+        }
+
+        private void Stop (bool force)
+        {
+            if (handle != IntPtr.Zero && (force || (addListeners.Count == 0 && removeListeners.Count == 0))) {
+                avahi_service_type_browser_free (handle);
+                handle = IntPtr.Zero;
+            }
+        }
+
+        private void OnServiceTypeBrowserCallback (IntPtr browser, int iface, Protocol proto, BrowserEvent bevent,
+                                                   IntPtr type, IntPtr domain, IntPtr userdata)
+        {
+
+            ServiceTypeInfo info;
+            info.NetworkInterface = iface;
+            info.Protocol = proto;
+            info.Domain = Utility.PtrToString (domain);
+            info.ServiceType = Utility.PtrToString (type);
+
+            infos.Add (info);
+            
+            if (bevent == BrowserEvent.Added) {
+                infos.Add (info);
+
+                foreach (ServiceTypeInfoHandler handler in addListeners)
+                    handler (this, info);
+            } else {
+                infos.Remove (info);
+
+                foreach (ServiceTypeInfoHandler handler in removeListeners)
+                    handler (this, info);
+            }
+        }
+    }
+}
diff --git a/avahi-sharp/Utility.cs b/avahi-sharp/Utility.cs
new file mode 100644 (file)
index 0000000..c621bed
--- /dev/null
@@ -0,0 +1,70 @@
+using System;
+using System.Net;
+using System.Text;
+using System.Runtime.InteropServices;
+using Mono.Unix;
+
+
+namespace Avahi
+{
+    internal class Utility
+    {
+        [DllImport ("libc")]
+        private static extern int strlen (IntPtr ptr);
+
+        [DllImport ("avahi-common")]
+        private static extern IntPtr avahi_address_snprint (IntPtr buf, int size, IntPtr address);
+
+        public static string PtrToString (IntPtr ptr)
+        {
+            if (ptr == IntPtr.Zero)
+                return null;
+            
+            int len = strlen (ptr);
+            byte[] bytes = new byte[len];
+            Marshal.Copy (ptr, bytes, 0, len);
+            return Encoding.UTF8.GetString (bytes);
+        }
+
+        public static string PtrToStringFree (IntPtr ptr)
+        {
+            if (ptr == IntPtr.Zero)
+                return null;
+            
+            string ret = PtrToString (ptr);
+            Free (ptr);
+            return ret;
+        }
+
+        public static IntPtr StringToPtr (string str)
+        {
+            if (str == null)
+                return IntPtr.Zero;
+
+            byte[] bytes = Encoding.UTF8.GetBytes (str);
+            IntPtr buf = Stdlib.malloc ((uint) bytes.Length + 1);
+            Marshal.Copy (bytes, 0, buf, bytes.Length);
+            Marshal.WriteByte (buf, bytes.Length, 0);
+            return buf;
+        }
+
+        public static void Free (IntPtr ptr)
+        {
+            Stdlib.free (ptr);
+        }
+
+        public static IPAddress PtrToAddress (IntPtr ptr)
+        {
+            IPAddress address = null;
+            
+            if (ptr != IntPtr.Zero) {
+                IntPtr buf = Stdlib.malloc (256);
+                IntPtr addrPtr = avahi_address_snprint (buf, 256, ptr);
+                address = IPAddress.Parse (Utility.PtrToString (addrPtr));
+                Utility.Free (addrPtr);
+            }
+
+            return address;
+        }
+    }
+}
index 8e63c4d0b4c8938ab983a80d094fb46c79051908..2986334eec5ad605c0a4445337020f492bffba80 100644 (file)
@@ -488,6 +488,7 @@ common/Makefile
 man/Makefile
 tests/Makefile
 service-type-database/Makefile
+avahi-sharp/Makefile
 ])
 AC_OUTPUT