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