]> git.meshlink.io Git - catta/blob - avahi-sharp/Client.cs
Complete AVAHI_LOOKUP_NO_ADDRESS fix
[catta] / avahi-sharp / Client.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
23 using System;
24 using System.Threading;
25 using System.Collections;
26 using System.Runtime.InteropServices;
27
28 namespace Avahi
29 {
30     internal enum ResolverEvent {
31         Found,
32         Timeout,
33         NotFound,
34         Failure
35     }
36     
37     internal enum BrowserEvent {
38         Added,
39         Removed,
40         CacheExhausted,
41         AllForNow,
42         NotFound,
43         Failure
44     }
45
46     internal delegate int PollCallback (IntPtr ufds, uint nfds, int timeout);
47     internal delegate void ClientCallback (IntPtr client, ClientState state, IntPtr userData);
48
49     public delegate void ClientStateHandler (object o, ClientState state);
50
51     public enum Protocol {
52         Unspecified = -1,
53         IPv4 = 0,
54         IPv6 = 1
55     }
56     
57     public enum ClientState {
58         Invalid,
59         Registering,
60         Running,
61         Collision,
62         Disconnected = 100
63     }
64
65     [Flags]
66     public enum LookupFlags {
67         None = 0,
68         UseWideArea = 1,
69         UseMulticast = 2,
70         NoTxt = 4,
71         NoAddress = 8
72     }
73
74     [Flags]
75     public enum LookupResultFlags {
76         None = 0,
77         Cached = 1,
78         WideArea = 2,
79         Multicast = 4
80     }
81     
82     public class Client : IDisposable
83     {
84         private IntPtr handle;
85         private ClientCallback cb;
86         private PollCallback pollcb;
87         private IntPtr spoll;
88
89         private Thread thread;
90
91         [DllImport ("avahi-client")]
92         private static extern IntPtr avahi_client_new (IntPtr poll, ClientCallback handler,
93                                                        IntPtr userData, out int error);
94
95         [DllImport ("avahi-client")]
96         private static extern void avahi_client_free (IntPtr handle);
97
98         [DllImport ("avahi-client")]
99         private static extern IntPtr avahi_client_get_version_string (IntPtr handle);
100
101         [DllImport ("avahi-client")]
102         private static extern IntPtr avahi_client_get_host_name (IntPtr handle);
103
104         [DllImport ("avahi-client")]
105         private static extern IntPtr avahi_client_get_domain_name (IntPtr handle);
106
107         [DllImport ("avahi-client")]
108         private static extern IntPtr avahi_client_get_host_name_fqdn (IntPtr handle);
109
110         [DllImport ("avahi-client")]
111         private static extern ClientState avahi_client_get_state (IntPtr handle);
112
113         [DllImport ("avahi-client")]
114         private static extern int avahi_client_errno (IntPtr handle);
115         
116         [DllImport ("avahi-common")]
117         private static extern IntPtr avahi_simple_poll_new ();
118
119         [DllImport ("avahi-common")]
120         private static extern IntPtr avahi_simple_poll_get (IntPtr spoll);
121
122         [DllImport ("avahi-common")]
123         private static extern void avahi_simple_poll_free (IntPtr spoll);
124
125         [DllImport ("avahi-common")]
126         private static extern int avahi_simple_poll_iterate (IntPtr spoll, int timeout);
127
128         [DllImport ("avahi-common")]
129         private static extern void avahi_simple_poll_set_func (IntPtr spoll, PollCallback cb);
130
131         [DllImport ("avahi-common")]
132         private static extern void avahi_simple_poll_quit (IntPtr spoll);
133
134         [DllImport ("avahi-client")]
135         private static extern uint avahi_client_get_local_service_cookie (IntPtr client);
136
137         [DllImport ("avahi-client")]
138         private static extern int avahi_client_is_service_local (IntPtr client, int iface, Protocol proto,
139                                                                  IntPtr name, IntPtr type, IntPtr domain);
140
141
142         [DllImport ("libc")]
143         private static extern int poll(IntPtr ufds, uint nfds, int timeout);
144
145         public event ClientStateHandler StateChanged;
146
147         internal IntPtr Handle
148         {
149             get { return handle; }
150         }
151         
152         public string Version
153         {
154             get {
155                 lock (this) {
156                     return Utility.PtrToString (avahi_client_get_version_string (handle));
157                 }
158             }
159         }
160
161         public string HostName
162         {
163             get {
164                 lock (this) {
165                     return Utility.PtrToString (avahi_client_get_host_name (handle));
166                 }
167             }
168         }
169
170         public string DomainName
171         {
172             get {
173                 lock (this) {
174                     return Utility.PtrToString (avahi_client_get_domain_name (handle));
175                 }
176             }
177         }
178
179         public string HostNameFqdn
180         {
181             get {
182                 lock (this) {
183                     return Utility.PtrToString (avahi_client_get_host_name_fqdn (handle));
184                 }
185             }
186         }
187
188         public ClientState State
189         {
190             get {
191                 lock (this) {
192                     return (ClientState) avahi_client_get_state (handle);
193                 }
194             }
195         }
196
197         public uint LocalServiceCookie
198         {
199             get {
200                 lock (this) {
201                     return avahi_client_get_local_service_cookie (handle);
202                 }
203             }
204         }
205
206         internal int LastError
207         {
208             get {
209                 lock (this) {
210                     return avahi_client_errno (handle);
211                 }
212             }
213         }
214
215         public Client ()
216         {
217             spoll = avahi_simple_poll_new ();
218
219             pollcb = OnPollCallback;
220             avahi_simple_poll_set_func (spoll, pollcb);
221             IntPtr poll = avahi_simple_poll_get (spoll);
222             cb = OnClientCallback;
223
224             int error;
225             handle = avahi_client_new (poll, cb, IntPtr.Zero, out error);
226             if (error != 0)
227                 throw new ClientException (error);
228
229             thread = new Thread (PollLoop);
230             thread.IsBackground = true;
231             thread.Start ();
232         }
233
234         ~Client ()
235         {
236             Dispose ();
237         }
238
239         public void Dispose ()
240         {
241             lock (this) {
242                 if (handle != IntPtr.Zero) {
243                     thread.Abort ();
244
245                     avahi_client_free (handle);
246                     avahi_simple_poll_quit (spoll);
247                     avahi_simple_poll_free (spoll);
248                     handle = IntPtr.Zero;
249                 }
250             }
251         }
252
253         public bool IsServiceLocal (ServiceInfo service)
254         {
255             return IsServiceLocal (service.NetworkInterface, service.Protocol, service.Name,
256                                    service.ServiceType, service.Domain);
257         }
258
259         public bool IsServiceLocal (int iface, Protocol proto, string name, string type, string domain)
260         {
261             IntPtr namePtr = Utility.StringToPtr (name);
262             IntPtr typePtr = Utility.StringToPtr (type);
263             IntPtr domainPtr = Utility.StringToPtr (domain);
264             
265             int result = avahi_client_is_service_local (handle, iface, proto, namePtr, typePtr, domainPtr);
266
267             Utility.Free (namePtr);
268             Utility.Free (typePtr);
269             Utility.Free (domainPtr);
270
271             return result == 1;
272         }
273
274         internal void CheckError ()
275         {
276             int error = LastError;
277
278             if (error != 0)
279                 throw new ClientException (error);
280         }
281         
282         private void OnClientCallback (IntPtr client, ClientState state, IntPtr userData)
283         {
284             if (StateChanged != null)
285                 StateChanged (this, state);
286         }
287
288         private int OnPollCallback (IntPtr ufds, uint nfds, int timeout) {
289             Monitor.Exit (this);
290             int result = poll (ufds, nfds, timeout);
291             Monitor.Enter (this);
292             return result;
293         }
294
295         private void PollLoop () {
296             try {
297                 lock (this) {
298                     while (true) {
299                         if (avahi_simple_poll_iterate (spoll, -1) != 0)
300                             break;
301                     }
302                 }
303             } catch (ThreadAbortException e) {
304             } catch (Exception e) {
305                 Console.Error.WriteLine ("Error in avahi-sharp event loop: " + e);
306             }
307         }
308     }
309 }