]> git.meshlink.io Git - catta/blob - avahi-sharp/ServiceBrowser.cs
lose the dep on avahi-glib, and run the avahi loop in a thread
[catta] / avahi-sharp / ServiceBrowser.cs
1 /* $Id$ */
2
3 /***
4   This file is part of avahi.
5
6   avahi is free software; you can redistribute it and/or modify it
7   under the terms of the GNU Lesser General Public License as
8   published by the Free Software Foundation; either version 2.1 of the
9   License, or (at your option) any later version.
10
11   avahi is distributed in the hope that it will be useful, but WITHOUT
12   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13   or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
14   Public License for more details.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with avahi; if not, write to the Free Software
18   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19   USA.
20 ***/
21
22 using System;
23 using System.Net;
24 using System.Collections;
25 using System.Runtime.InteropServices;
26
27 namespace Avahi
28 {
29     internal delegate void ServiceBrowserCallback (IntPtr browser, int iface, Protocol proto, BrowserEvent bevent,
30                                                    IntPtr name, IntPtr type, IntPtr domain, IntPtr userdata);
31     
32     public struct ServiceInfo
33     {
34         public int NetworkInterface;
35         public Protocol Protocol;
36         public string Domain;
37         public string ServiceType;
38         public string Name;
39
40         public string HostName;
41         public IPAddress Address;
42         public UInt16 Port;
43         public byte[][] Text;
44
45         public static ServiceInfo Zero = new ServiceInfo ();
46     }
47
48     public delegate void ServiceInfoHandler (object o, ServiceInfo info);
49     
50     public class ServiceBrowser : IDisposable
51     {
52         private IntPtr handle;
53         private ArrayList infos = new ArrayList ();
54         private Client client;
55         private int iface;
56         private Protocol proto;
57         private string domain;
58         private string type;
59         private ServiceBrowserCallback cb;
60
61         private ArrayList addListeners = new ArrayList ();
62         private ArrayList removeListeners = new ArrayList ();
63         
64         [DllImport ("avahi-client")]
65         private static extern IntPtr avahi_service_browser_new (IntPtr client, int iface, int proto, IntPtr type,
66                                                                 IntPtr domain, ServiceBrowserCallback cb,
67                                                                 IntPtr userdata);
68
69         [DllImport ("avahi-client")]
70         private static extern void avahi_service_browser_free (IntPtr handle);
71
72         public event ServiceInfoHandler ServiceAdded
73         {
74             add {
75                 addListeners.Add (value);
76                 Start ();
77             }
78             remove {
79                 addListeners.Remove (value);
80                 Stop (false);
81             }
82         }
83         
84         public event ServiceInfoHandler ServiceRemoved
85         {
86             add {
87                 removeListeners.Add (value);
88                 Start ();
89             }
90             remove {
91                 removeListeners.Remove (value);
92                 Stop (false);
93             }
94         }
95
96         public ServiceInfo[] Services
97         {
98             get { return (ServiceInfo[]) infos.ToArray (typeof (ServiceInfo)); }
99         }
100
101         public ServiceBrowser (Client client, string type) : this (client, type, client.DomainName)
102         {
103         }
104         
105         public ServiceBrowser (Client client, string type, string domain) : this (client, -1, Protocol.Unspecified,
106                                                                                   type, domain)
107         {
108         }
109         
110         public ServiceBrowser (Client client, int iface, Protocol proto, string type, string domain)
111         {
112             this.client = client;
113             this.iface = iface;
114             this.proto = proto;
115             this.domain = domain;
116             this.type = type;
117             cb = OnServiceBrowserCallback;
118         }
119
120         ~ServiceBrowser ()
121         {
122             Dispose ();
123         }
124
125         public void Dispose ()
126         {
127             Stop (true);
128         }
129
130         private void Start ()
131         {
132             if (client.Handle == IntPtr.Zero || handle != IntPtr.Zero ||
133                 (addListeners.Count == 0 && removeListeners.Count == 0))
134                 return;
135
136             IntPtr domainPtr = Utility.StringToPtr (domain);
137             IntPtr typePtr = Utility.StringToPtr (type);
138
139             lock (client) {
140                 handle = avahi_service_browser_new (client.Handle, iface, (int) proto, typePtr, domainPtr,
141                                                     cb, IntPtr.Zero);
142             }
143             Utility.Free (domainPtr);
144             Utility.Free (typePtr);
145         }
146
147         private void Stop (bool force)
148         {
149             if (client.Handle != IntPtr.Zero && handle != IntPtr.Zero &&
150                 (force || (addListeners.Count == 0 && removeListeners.Count == 0))) {
151                 
152                 lock (client) {
153                     avahi_service_browser_free (handle);
154                     handle = IntPtr.Zero;
155                 }
156             }
157         }
158
159         private void OnServiceBrowserCallback (IntPtr browser, int iface, Protocol proto, BrowserEvent bevent,
160                                                IntPtr name, IntPtr type, IntPtr domain, IntPtr userdata)
161         {
162
163             ServiceInfo info;
164             info.NetworkInterface = iface;
165             info.Protocol = proto;
166             info.Domain = Utility.PtrToString (domain);
167             info.ServiceType = Utility.PtrToString (type);
168             info.Name = Utility.PtrToString (name);
169             info.HostName = null;
170             info.Address = null;
171             info.Port = 0;
172             info.Text = null;
173
174             infos.Add (info);
175             
176             if (bevent == BrowserEvent.Added) {
177                 infos.Add (info);
178
179                 foreach (ServiceInfoHandler handler in addListeners)
180                     handler (this, info);
181             } else {
182                 infos.Remove (info);
183
184                 foreach (ServiceInfoHandler handler in removeListeners)
185                     handler (this, info);
186             }
187         }
188     }
189 }