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