--- /dev/null
+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 ());
+ }
+ }
+ }
+}
--- /dev/null
+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);
+ }
+}
--- /dev/null
+
+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);
+ }
+ }
+}
--- /dev/null
+
+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);
+ }
+ }
+}
--- /dev/null
+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);
+ }
+ }
+ }
+}
--- /dev/null
+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);
+ }
+ }
+}
--- /dev/null
+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 ());
+ }
+ }
+ }
+}
--- /dev/null
+
+
+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
--- /dev/null
+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);
+ }
+ }
+ }
+}
--- /dev/null
+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 ());
+ }
+ }
+ }
+}
--- /dev/null
+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);
+ }
+ }
+ }
+}
--- /dev/null
+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;
+ }
+ }
+}
man/Makefile
tests/Makefile
service-type-database/Makefile
+avahi-sharp/Makefile
])
AC_OUTPUT