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.Collections;
22 using System.Net;
23 using System.Runtime.InteropServices;
24 using System.Text;
25 using Mono.Unix;
26 
27 namespace Avahi
28 {
29 
HostNameResolverCallback(IntPtr resolver, int iface, Protocol proto, ResolverEvent revent, IntPtr hostname, IntPtr address, LookupResultFlags flags, IntPtr userdata)30     internal delegate void HostNameResolverCallback (IntPtr resolver, int iface, Protocol proto,
31                                                      ResolverEvent revent, IntPtr hostname, IntPtr address,
32                                                      LookupResultFlags flags, IntPtr userdata);
33 
34     public class HostNameResolver : ResolverBase, IDisposable
35     {
36         private IntPtr handle;
37         private Client client;
38         private int iface;
39         private Protocol proto;
40         private string hostname;
41         private Protocol aproto;
42         private LookupFlags flags;
43         private HostNameResolverCallback cb;
44 
45         private IPAddress currentAddress;
46         private string currentHost;
47 
48         private ArrayList foundListeners = new ArrayList ();
49         private ArrayList timeoutListeners = new ArrayList ();
50 
51         [DllImport ("avahi-client")]
avahi_host_name_resolver_new(IntPtr client, int iface, Protocol proto, byte[] hostname, Protocol aproto, LookupFlags flags, HostNameResolverCallback cb, IntPtr userdata)52         private static extern IntPtr avahi_host_name_resolver_new (IntPtr client, int iface, Protocol proto,
53                                                                    byte[] hostname, Protocol aproto, LookupFlags flags,
54                                                                    HostNameResolverCallback cb, IntPtr userdata);
55 
56         [DllImport ("avahi-client")]
avahi_host_name_resolver_free(IntPtr handle)57         private static extern void avahi_host_name_resolver_free (IntPtr handle);
58 
59         public event HostAddressHandler Found
60         {
61             add {
62                 foundListeners.Add (value);
63                 Start ();
64             }
65             remove {
66                 foundListeners.Remove (value);
67                 Stop (false);
68             }
69         }
70 
71         public event EventHandler Timeout
72         {
73             add {
74                 timeoutListeners.Add (value);
75                 Start ();
76             }
77             remove {
78                 timeoutListeners.Remove (value);
79                 Stop (false);
80             }
81         }
82 
83         public IPAddress Address
84         {
85             get { return currentAddress; }
86         }
87 
88         public string HostName
89         {
90             get { return currentHost; }
91         }
92 
HostNameResolver(Client client, string hostname)93         public HostNameResolver (Client client, string hostname) : this (client, -1, Protocol.Unspecified,
94                                                                          hostname, Protocol.Unspecified,
95                                                                          LookupFlags.None)
96         {
97         }
98 
HostNameResolver(Client client, int iface, Protocol proto, string hostname, Protocol aproto, LookupFlags flags)99         public HostNameResolver (Client client, int iface, Protocol proto, string hostname,
100                                  Protocol aproto, LookupFlags flags)
101         {
102             this.client = client;
103             this.iface = iface;
104             this.proto = proto;
105             this.hostname = hostname;
106             this.aproto = aproto;
107             this.flags = flags;
108             cb = OnHostNameResolverCallback;
109         }
110 
~HostNameResolver()111         ~HostNameResolver ()
112         {
113             Dispose ();
114         }
115 
Dispose()116         public void Dispose ()
117         {
118             Stop (true);
119         }
120 
Start()121         private void Start ()
122         {
123             if (client.Handle == IntPtr.Zero || handle != IntPtr.Zero ||
124                 (foundListeners.Count == 0 && timeoutListeners.Count == 0))
125                 return;
126 
127             lock (client) {
128                 handle = avahi_host_name_resolver_new (client.Handle, iface, proto,
129                                                        Utility.StringToBytes (hostname), aproto, flags,
130                                                        cb, IntPtr.Zero);
131 
132                 if (handle == IntPtr.Zero)
133                     client.ThrowError ();
134             }
135         }
136 
Stop(bool force)137         private void Stop (bool force)
138         {
139             if (client.Handle != IntPtr.Zero && handle != IntPtr.Zero &&
140                 (force || (foundListeners.Count == 0 && timeoutListeners.Count == 0))) {
141 
142                 lock (client) {
143                     avahi_host_name_resolver_free (handle);
144                     handle = IntPtr.Zero;
145                 }
146             }
147         }
148 
OnHostNameResolverCallback(IntPtr resolver, int iface, Protocol proto, ResolverEvent revent, IntPtr hostname, IntPtr address, LookupResultFlags flags, IntPtr userdata)149         private void OnHostNameResolverCallback (IntPtr resolver, int iface, Protocol proto,
150                                                  ResolverEvent revent, IntPtr hostname, IntPtr address,
151                                                  LookupResultFlags flags, IntPtr userdata)
152         {
153             switch (revent) {
154             case ResolverEvent.Found:
155                 currentAddress = Utility.PtrToAddress (address);
156                 currentHost = Utility.PtrToString (hostname);
157 
158                 foreach (HostAddressHandler handler in foundListeners)
159                     handler (this, new HostAddressArgs (currentHost, currentAddress));
160                 break;
161             case ResolverEvent.Failure:
162                 EmitFailure (client.LastError);
163                 break;
164             }
165         }
166     }
167 }
168