]> git.meshlink.io Git - catta/blob - avahi-sharp/ServiceBrowser.cs
Complete AVAHI_LOOKUP_NO_ADDRESS fix
[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, LookupResultFlags flags,
31                                                    IntPtr userdata);
32     
33     public struct ServiceInfo
34     {
35         public int NetworkInterface;
36         public Protocol Protocol;
37         public string Domain;
38         public string ServiceType;
39         public string Name;
40
41         public string HostName;
42         public IPAddress Address;
43         public UInt16 Port;
44         public byte[][] Text;
45         public LookupResultFlags Flags;
46
47         public static ServiceInfo Zero = new ServiceInfo ();
48     }
49
50     public delegate void ServiceInfoHandler (object o, ServiceInfo info);
51     
52     public class ServiceBrowser : BrowserBase, IDisposable
53     {
54         private IntPtr handle;
55         private ArrayList infos = new ArrayList ();
56         private Client client;
57         private int iface;
58         private Protocol proto;
59         private string domain;
60         private string type;
61         private LookupFlags flags;
62         private ServiceBrowserCallback cb;
63
64         private ArrayList addListeners = new ArrayList ();
65         private ArrayList removeListeners = new ArrayList ();
66         
67         [DllImport ("avahi-client")]
68         private static extern IntPtr avahi_service_browser_new (IntPtr client, int iface, int proto, IntPtr type,
69                                                                 IntPtr domain, LookupFlags flags,
70                                                                 ServiceBrowserCallback cb,
71                                                                 IntPtr userdata);
72
73         [DllImport ("avahi-client")]
74         private static extern void avahi_service_browser_free (IntPtr handle);
75
76         public event ServiceInfoHandler ServiceAdded
77         {
78             add {
79                 addListeners.Add (value);
80                 Start ();
81             }
82             remove {
83                 addListeners.Remove (value);
84                 Stop (false);
85             }
86         }
87         
88         public event ServiceInfoHandler ServiceRemoved
89         {
90             add {
91                 removeListeners.Add (value);
92                 Start ();
93             }
94             remove {
95                 removeListeners.Remove (value);
96                 Stop (false);
97             }
98         }
99
100         public ServiceInfo[] Services
101         {
102             get { return (ServiceInfo[]) infos.ToArray (typeof (ServiceInfo)); }
103         }
104
105         public ServiceBrowser (Client client, string type) : this (client, type, client.DomainName)
106         {
107         }
108         
109         public ServiceBrowser (Client client, string type, string domain) : this (client, -1, Protocol.Unspecified,
110                                                                                   type, domain, LookupFlags.None)
111         {
112         }
113         
114         public ServiceBrowser (Client client, int iface, Protocol proto, string type, string domain, LookupFlags flags)
115         {
116             this.client = client;
117             this.iface = iface;
118             this.proto = proto;
119             this.domain = domain;
120             this.type = type;
121             this.flags = flags;
122             cb = OnServiceBrowserCallback;
123         }
124
125         ~ServiceBrowser ()
126         {
127             Dispose ();
128         }
129
130         public void Dispose ()
131         {
132             Stop (true);
133         }
134
135         private void Start ()
136         {
137             if (client.Handle == IntPtr.Zero || handle != IntPtr.Zero ||
138                 (addListeners.Count == 0 && removeListeners.Count == 0))
139                 return;
140
141             IntPtr domainPtr = Utility.StringToPtr (domain);
142             IntPtr typePtr = Utility.StringToPtr (type);
143
144             lock (client) {
145                 handle = avahi_service_browser_new (client.Handle, iface, (int) proto, typePtr, domainPtr, flags,
146                                                     cb, IntPtr.Zero);
147             }
148             Utility.Free (domainPtr);
149             Utility.Free (typePtr);
150         }
151
152         private void Stop (bool force)
153         {
154             if (client.Handle != IntPtr.Zero && handle != IntPtr.Zero &&
155                 (force || (addListeners.Count == 0 && removeListeners.Count == 0))) {
156                 
157                 lock (client) {
158                     avahi_service_browser_free (handle);
159                     handle = IntPtr.Zero;
160                 }
161             }
162         }
163
164         private void OnServiceBrowserCallback (IntPtr browser, int iface, Protocol proto, BrowserEvent bevent,
165                                                IntPtr name, IntPtr type, IntPtr domain, LookupResultFlags flags,
166                                                IntPtr userdata)
167         {
168
169             ServiceInfo info;
170             info.NetworkInterface = iface;
171             info.Protocol = proto;
172             info.Domain = Utility.PtrToString (domain);
173             info.ServiceType = Utility.PtrToString (type);
174             info.Name = Utility.PtrToString (name);
175             info.HostName = null;
176             info.Address = null;
177             info.Port = 0;
178             info.Text = null;
179             info.Flags = flags;
180
181             infos.Add (info);
182
183             switch (bevent) {
184             case BrowserEvent.Added:
185                 infos.Add (info);
186
187                 foreach (ServiceInfoHandler handler in addListeners)
188                     handler (this, info);
189
190                 break;
191             case BrowserEvent.Removed:
192                 infos.Remove (info);
193
194                 foreach (ServiceInfoHandler handler in removeListeners)
195                     handler (this, info);
196
197                 break;
198             default:
199                 EmitBrowserEvent (bevent);
200                 break;
201             }
202         }
203     }
204 }