From 264700bf97de2e4430494cb41201950162fba020 Mon Sep 17 00:00:00 2001 From: James Willcox Date: Wed, 14 Sep 2005 02:32:27 +0000 Subject: lose the dep on avahi-glib, and run the avahi loop in a thread git-svn-id: file:///home/lennart/svn/public/avahi/trunk@580 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe --- avahi-sharp/AddressResolver.cs | 21 +++++-- avahi-sharp/Client.cs | 115 ++++++++++++++++++++++++++++++++------ avahi-sharp/DomainBrowser.cs | 22 +++++--- avahi-sharp/EntryGroup.cs | 49 +++++++++++----- avahi-sharp/HostNameResolver.cs | 21 +++++-- avahi-sharp/ServiceBrowser.cs | 20 +++++-- avahi-sharp/ServiceResolver.cs | 22 +++++--- avahi-sharp/ServiceTypeBrowser.cs | 23 +++++--- 8 files changed, 222 insertions(+), 71 deletions(-) diff --git a/avahi-sharp/AddressResolver.cs b/avahi-sharp/AddressResolver.cs index 6b0d030..c462346 100644 --- a/avahi-sharp/AddressResolver.cs +++ b/avahi-sharp/AddressResolver.cs @@ -116,20 +116,29 @@ namespace Avahi private void Start () { - if (handle != IntPtr.Zero || (foundListeners.Count == 0 && timeoutListeners.Count == 0)) + if (client.Handle == IntPtr.Zero || 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, - cb, IntPtr.Zero); + + lock (client) { + handle = avahi_address_resolver_new (client.Handle, iface, proto, addrPtr, + cb, 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; + if (client.Handle != IntPtr.Zero && handle != IntPtr.Zero && + (force || (foundListeners.Count == 0 && timeoutListeners.Count == 0))) { + + lock (client) { + avahi_address_resolver_free (handle); + handle = IntPtr.Zero; + } } } diff --git a/avahi-sharp/Client.cs b/avahi-sharp/Client.cs index 84069fc..c3584c5 100644 --- a/avahi-sharp/Client.cs +++ b/avahi-sharp/Client.cs @@ -21,6 +21,7 @@ using System; +using System.Threading; using System.Collections; using System.Runtime.InteropServices; @@ -35,7 +36,8 @@ namespace Avahi Added, Removed } - + + internal delegate int PollCallback (IntPtr ufds, uint nfds, int timeout); internal delegate void ClientCallback (IntPtr client, ClientState state, IntPtr userData); public delegate void ClientStateHandler (object o, ClientState state); @@ -57,6 +59,11 @@ namespace Avahi public class Client : IDisposable { private IntPtr handle; + private ClientCallback cb; + private PollCallback pollcb; + private IntPtr spoll; + + private Thread thread; [DllImport ("avahi-client")] private static extern IntPtr avahi_client_new (IntPtr poll, ClientCallback handler, @@ -83,11 +90,26 @@ namespace Avahi [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-common")] + private static extern IntPtr avahi_simple_poll_new (); + + [DllImport ("avahi-common")] + private static extern IntPtr avahi_simple_poll_get (IntPtr spoll); + + [DllImport ("avahi-common")] + private static extern void avahi_simple_poll_free (IntPtr spoll); + + [DllImport ("avahi-common")] + private static extern int avahi_simple_poll_iterate (IntPtr spoll, int timeout); - [DllImport ("avahi-glib")] - private static extern IntPtr avahi_glib_poll_get (IntPtr gpoll); + [DllImport ("avahi-common")] + private static extern void avahi_simple_poll_set_func (IntPtr spoll, PollCallback cb); + + [DllImport ("avahi-common")] + private static extern void avahi_simple_poll_quit (IntPtr spoll); + + [DllImport ("libc")] + private static extern int poll(IntPtr ufds, uint nfds, int timeout); public event ClientStateHandler StateChanged; @@ -98,43 +120,75 @@ namespace Avahi public string Version { - get { return Utility.PtrToString (avahi_client_get_version_string (handle)); } + get { + lock (this) { + return Utility.PtrToString (avahi_client_get_version_string (handle)); + } + } } public string HostName { - get { return Utility.PtrToString (avahi_client_get_host_name (handle)); } + get { + lock (this) { + return Utility.PtrToString (avahi_client_get_host_name (handle)); + } + } } public string DomainName { - get { return Utility.PtrToString (avahi_client_get_domain_name (handle)); } + get { + lock (this) { + return Utility.PtrToString (avahi_client_get_domain_name (handle)); + } + } } public string HostNameFqdn { - get { return Utility.PtrToString (avahi_client_get_host_name_fqdn (handle)); } + get { + lock (this) { + return Utility.PtrToString (avahi_client_get_host_name_fqdn (handle)); + } + } } public ClientState State { - get { return (ClientState) avahi_client_get_state (handle); } + get { + lock (this) { + return (ClientState) avahi_client_get_state (handle); + } + } } internal int LastError { - get { return avahi_client_errno (handle); } + get { + lock (this) { + return avahi_client_errno (handle); + } + } } public Client () { - IntPtr gpoll = avahi_glib_poll_new (IntPtr.Zero, 0); - IntPtr poll = avahi_glib_poll_get (gpoll); + spoll = avahi_simple_poll_new (); + + pollcb = OnPollCallback; + avahi_simple_poll_set_func (spoll, pollcb); + IntPtr poll = avahi_simple_poll_get (spoll); + cb = OnClientCallback; int error; - handle = avahi_client_new (poll, OnClientCallback, IntPtr.Zero, out error); + handle = avahi_client_new (poll, cb, IntPtr.Zero, out error); if (error != 0) throw new ClientException (error); + + thread = new Thread (PollLoop); + thread.IsBackground = true; + thread.Start (); } ~Client () @@ -144,9 +198,15 @@ namespace Avahi public void Dispose () { - if (handle != IntPtr.Zero) { - avahi_client_free (handle); - handle = IntPtr.Zero; + lock (this) { + if (handle != IntPtr.Zero) { + thread.Abort (); + + avahi_client_free (handle); + avahi_simple_poll_quit (spoll); + avahi_simple_poll_free (spoll); + handle = IntPtr.Zero; + } } } @@ -163,5 +223,26 @@ namespace Avahi if (StateChanged != null) StateChanged (this, state); } + + private int OnPollCallback (IntPtr ufds, uint nfds, int timeout) { + Monitor.Exit (this); + int result = poll (ufds, nfds, timeout); + Monitor.Enter (this); + return result; + } + + private void PollLoop () { + try { + lock (this) { + while (true) { + if (avahi_simple_poll_iterate (spoll, -1) != 0) + break; + } + } + } catch (ThreadAbortException e) { + } catch (Exception e) { + Console.Error.WriteLine ("Error in avahi-sharp event loop: " + e); + } + } } } diff --git a/avahi-sharp/DomainBrowser.cs b/avahi-sharp/DomainBrowser.cs index cc93641..76438f8 100644 --- a/avahi-sharp/DomainBrowser.cs +++ b/avahi-sharp/DomainBrowser.cs @@ -122,20 +122,26 @@ namespace Avahi private void Start () { - if (handle != IntPtr.Zero || (addListeners.Count == 0 && removeListeners.Count == 0)) + if (client.Handle == IntPtr.Zero && 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, - cb, IntPtr.Zero); - Utility.Free (domainPtr); + lock (client) { + IntPtr domainPtr = Utility.StringToPtr (domain); + handle = avahi_domain_browser_new (client.Handle, iface, (int) proto, domainPtr, (int) btype, + cb, 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; + if (client.Handle != IntPtr.Zero && handle != IntPtr.Zero && + (force || (addListeners.Count == 0 && removeListeners.Count == 0))) { + lock (client) { + avahi_domain_browser_free (handle); + handle = IntPtr.Zero; + } } } diff --git a/avahi-sharp/EntryGroup.cs b/avahi-sharp/EntryGroup.cs index d69e8a6..142029a 100644 --- a/avahi-sharp/EntryGroup.cs +++ b/avahi-sharp/EntryGroup.cs @@ -40,6 +40,7 @@ namespace Avahi { private Client client; private IntPtr handle; + private EntryGroupCallback cb; [DllImport ("avahi-client")] private static extern IntPtr avahi_entry_group_new (IntPtr client, EntryGroupCallback cb, IntPtr userdata); @@ -77,19 +78,31 @@ namespace Avahi public EntryGroupState State { - get { return avahi_entry_group_get_state (handle); } + get { + lock (client) { + return avahi_entry_group_get_state (handle); + } + } } public bool IsEmpty { - get { return avahi_entry_group_is_empty (handle); } + get { + lock (client) { + 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 (); + cb = OnEntryGroupCallback; + + lock (client) { + handle = avahi_entry_group_new (client.Handle, cb, IntPtr.Zero); + client.CheckError (); + } } ~EntryGroup () @@ -99,22 +112,28 @@ namespace Avahi public void Dispose () { - if (handle != IntPtr.Zero) { - avahi_entry_group_free (handle); - handle = IntPtr.Zero; + if (client.Handle != IntPtr.Zero && handle != IntPtr.Zero) { + lock (client) { + avahi_entry_group_free (handle); + handle = IntPtr.Zero; + } } } public void Commit () { - avahi_entry_group_commit (handle); - client.CheckError (); + lock (client) { + avahi_entry_group_commit (handle); + client.CheckError (); + } } public void Reset () { - avahi_entry_group_reset (handle); - client.CheckError (); + lock (client) { + avahi_entry_group_reset (handle); + client.CheckError (); + } } public void AddService (string name, string type, string domain, @@ -140,8 +159,12 @@ namespace Avahi 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); + + lock (client) { + avahi_entry_group_add_service_strlst (handle, iface, proto, namePtr, typePtr, domainPtr, + hostPtr, port, list); + } + avahi_string_list_free (list); client.CheckError (); diff --git a/avahi-sharp/HostNameResolver.cs b/avahi-sharp/HostNameResolver.cs index a8cf0f1..d522cea 100644 --- a/avahi-sharp/HostNameResolver.cs +++ b/avahi-sharp/HostNameResolver.cs @@ -118,20 +118,29 @@ namespace Avahi private void Start () { - if (handle != IntPtr.Zero || (foundListeners.Count == 0 && timeoutListeners.Count == 0)) + if (client.Handle == IntPtr.Zero || 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, - cb, IntPtr.Zero); + + lock (client) { + handle = avahi_host_name_resolver_new (client.Handle, iface, proto, hostPtr, aproto, + cb, 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; + if (client.Handle != IntPtr.Zero && handle != IntPtr.Zero && + (force || (foundListeners.Count == 0 && timeoutListeners.Count == 0))) { + + lock (client) { + avahi_host_name_resolver_free (handle); + handle = IntPtr.Zero; + } } } diff --git a/avahi-sharp/ServiceBrowser.cs b/avahi-sharp/ServiceBrowser.cs index a96040c..5da7ea4 100644 --- a/avahi-sharp/ServiceBrowser.cs +++ b/avahi-sharp/ServiceBrowser.cs @@ -129,22 +129,30 @@ namespace Avahi private void Start () { - if (handle != IntPtr.Zero || (addListeners.Count == 0 && removeListeners.Count == 0)) + if (client.Handle == IntPtr.Zero || 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, - cb, IntPtr.Zero); + + lock (client) { + handle = avahi_service_browser_new (client.Handle, iface, (int) proto, typePtr, domainPtr, + cb, 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; + if (client.Handle != IntPtr.Zero && handle != IntPtr.Zero && + (force || (addListeners.Count == 0 && removeListeners.Count == 0))) { + + lock (client) { + avahi_service_browser_free (handle); + handle = IntPtr.Zero; + } } } diff --git a/avahi-sharp/ServiceResolver.cs b/avahi-sharp/ServiceResolver.cs index 558ba53..8e8464b 100644 --- a/avahi-sharp/ServiceResolver.cs +++ b/avahi-sharp/ServiceResolver.cs @@ -135,14 +135,19 @@ namespace Avahi private void Start () { - if (handle != IntPtr.Zero || (foundListeners.Count == 0 && timeoutListeners.Count == 0)) + if (client.Handle == IntPtr.Zero || 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, cb, IntPtr.Zero); + + lock (client) { + handle = avahi_service_resolver_new (client.Handle, iface, proto, namePtr, typePtr, domainPtr, + aproto, cb, IntPtr.Zero); + } + Utility.Free (namePtr); Utility.Free (typePtr); Utility.Free (domainPtr); @@ -150,9 +155,13 @@ namespace Avahi private void Stop (bool force) { - if (handle != IntPtr.Zero && (force || (foundListeners.Count == 0 && timeoutListeners.Count == 0))) { - avahi_service_resolver_free (handle); - handle = IntPtr.Zero; + if (client.Handle != IntPtr.Zero && handle != IntPtr.Zero && + (force || (foundListeners.Count == 0 && timeoutListeners.Count == 0))) { + + lock (client) { + avahi_service_resolver_free (handle); + handle = IntPtr.Zero; + } } } @@ -161,7 +170,6 @@ namespace Avahi IntPtr domain, IntPtr host, IntPtr address, UInt16 port, IntPtr txt, IntPtr userdata) { - ServiceInfo info; info.NetworkInterface = iface; info.Protocol = proto; diff --git a/avahi-sharp/ServiceTypeBrowser.cs b/avahi-sharp/ServiceTypeBrowser.cs index e436da9..ab6a866 100644 --- a/avahi-sharp/ServiceTypeBrowser.cs +++ b/avahi-sharp/ServiceTypeBrowser.cs @@ -117,20 +117,27 @@ namespace Avahi private void Start () { - if (handle != IntPtr.Zero || (addListeners.Count == 0 && removeListeners.Count == 0)) + if (client.Handle == IntPtr.Zero || 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, - cb, IntPtr.Zero); - Utility.Free (domainPtr); + lock (client) { + IntPtr domainPtr = Utility.StringToPtr (domain); + handle = avahi_service_type_browser_new (client.Handle, iface, (int) proto, domainPtr, + cb, 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; + if (client.Handle != IntPtr.Zero && handle != IntPtr.Zero && + (force || (addListeners.Count == 0 && removeListeners.Count == 0))) { + + lock (client) { + avahi_service_type_browser_free (handle); + handle = IntPtr.Zero; + } } } -- cgit