]> git.meshlink.io Git - catta/blob - avahi-sharp/HostNameResolver.cs
fix avahi_netlink_new to allow multiple netlinks per process
[catta] / avahi-sharp / HostNameResolver.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.Collections;
22 using System.Net;
23 using System.Runtime.InteropServices;
24 using System.Text;
25 using Mono.Unix;
26
27 namespace Avahi
28 {
29
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")]
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")]
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
93         public HostNameResolver (Client client, string hostname) : this (client, -1, Protocol.Unspecified,
94                                                                          hostname, Protocol.Unspecified,
95                                                                          LookupFlags.None)
96         {
97         }
98
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
111         ~HostNameResolver ()
112         {
113             Dispose ();
114         }
115
116         public void Dispose ()
117         {
118             Stop (true);
119         }
120
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
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
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 }