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