]> git.meshlink.io Git - catta/blob - avahi-sharp/ServiceResolver.cs
558ba539d6ac86c4532f51287077130572e16789
[catta] / avahi-sharp / ServiceResolver.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 using System;
23 using System.Collections;
24 using System.Net;
25 using System.Runtime.InteropServices;
26 using Mono.Unix;
27
28 namespace Avahi
29 {
30
31     internal delegate void ServiceResolverCallback (IntPtr resolver, int iface, Protocol proto,
32                                                     ResolverEvent revent, IntPtr name, IntPtr type,
33                                                     IntPtr domain, IntPtr host, IntPtr address,
34                                                     UInt16 port, IntPtr txt, IntPtr userdata);
35
36     public class ServiceResolver : IDisposable
37     {
38         private IntPtr handle;
39         private ServiceInfo currentInfo;
40         private Client client;
41         private int iface;
42         private Protocol proto;
43         private string name;
44         private string type;
45         private string domain;
46         private Protocol aproto;
47         private ServiceResolverCallback cb;
48
49         private ArrayList foundListeners = new ArrayList ();
50         private ArrayList timeoutListeners = new ArrayList ();
51         
52         [DllImport ("avahi-client")]
53         private static extern IntPtr avahi_service_resolver_new (IntPtr client, int iface, Protocol proto,
54                                                                  IntPtr name, IntPtr type, IntPtr domain,
55                                                                  Protocol aproto, ServiceResolverCallback cb,
56                                                                  IntPtr userdata);
57
58         [DllImport ("avahi-common")]
59         private static extern IntPtr avahi_string_list_get_next (IntPtr list);
60
61         [DllImport ("avahi-common")]
62         private static extern IntPtr avahi_string_list_get_text (IntPtr list);
63
64         [DllImport ("avahi-common")]
65         private static extern int avahi_string_list_get_size (IntPtr list);
66
67         [DllImport ("avahi-client")]
68         private static extern void avahi_service_resolver_free (IntPtr handle);
69
70         public event ServiceInfoHandler Found
71         {
72             add {
73                 foundListeners.Add (value);
74                 Start ();
75             }
76             remove {
77                 foundListeners.Remove (value);
78                 Stop (false);
79             }
80         }
81         
82         public event EventHandler Timeout
83         {
84             add {
85                 timeoutListeners.Add (value);
86                 Start ();
87             }
88             remove {
89                 timeoutListeners.Remove (value);
90                 Stop (false);
91             }
92         }
93
94         public ServiceInfo Service
95         {
96             get { return currentInfo; }
97         }
98
99         public ServiceResolver (Client client, string name, string type, string domain) : this (client, -1,
100                                                                                                 Protocol.Unspecified,
101                                                                                                 name, type, domain,
102                                                                                                 Protocol.Unspecified)
103         {
104         }
105
106         public ServiceResolver (Client client, ServiceInfo service) : this (client, service.NetworkInterface,
107                                                                             service.Protocol, service.Name,
108                                                                             service.ServiceType, service.Domain,
109                                                                             Protocol.Unspecified)
110         {
111         }
112         
113         public ServiceResolver (Client client, int iface, Protocol proto, string name,
114                                 string type, string domain, Protocol aproto)
115         {
116             this.client = client;
117             this.iface = iface;
118             this.proto = proto;
119             this.name = name;
120             this.type = type;
121             this.domain = domain;
122             this.aproto = aproto;
123             cb = OnServiceResolverCallback;
124         }
125
126         ~ServiceResolver ()
127         {
128             Dispose ();
129         }
130
131         public void Dispose ()
132         {
133             Stop (true);
134         }
135
136         private void Start ()
137         {
138             if (handle != IntPtr.Zero || (foundListeners.Count == 0 && timeoutListeners.Count == 0))
139                 return;
140
141             IntPtr namePtr = Utility.StringToPtr (name);
142             IntPtr typePtr = Utility.StringToPtr (type);
143             IntPtr domainPtr = Utility.StringToPtr (domain);
144             handle = avahi_service_resolver_new (client.Handle, iface, proto, namePtr, typePtr, domainPtr,
145                                                  aproto, cb, IntPtr.Zero);
146             Utility.Free (namePtr);
147             Utility.Free (typePtr);
148             Utility.Free (domainPtr);
149         }
150
151         private void Stop (bool force)
152         {
153             if (handle != IntPtr.Zero && (force || (foundListeners.Count == 0 && timeoutListeners.Count == 0))) {
154                 avahi_service_resolver_free (handle);
155                 handle = IntPtr.Zero;
156             }
157         }
158
159         private void OnServiceResolverCallback (IntPtr resolver, int iface, Protocol proto,
160                                                 ResolverEvent revent, IntPtr name, IntPtr type,
161                                                 IntPtr domain, IntPtr host, IntPtr address,
162                                                 UInt16 port, IntPtr txt, IntPtr userdata)
163         {
164
165             ServiceInfo info;
166             info.NetworkInterface = iface;
167             info.Protocol = proto;
168             info.Domain = Utility.PtrToString (domain);
169             info.ServiceType = Utility.PtrToString (type);
170             info.Name = Utility.PtrToString (name);
171             info.HostName = Utility.PtrToString (host);
172             info.Address = Utility.PtrToAddress (address);
173             info.Port = port;
174
175             ArrayList txtlist = new ArrayList ();
176             for (IntPtr l = txt; l != IntPtr.Zero; l = avahi_string_list_get_next (l)) {
177                 IntPtr buf = avahi_string_list_get_text (l);
178                 int len = avahi_string_list_get_size (l);
179
180                 byte[] txtbuf = new byte[len];
181                 Marshal.Copy (buf, txtbuf, 0, len);
182                 txtlist.Add (txtbuf);
183             }
184
185             info.Text = (byte[][]) txtlist.ToArray (typeof (byte[]));
186             
187             if (revent == ResolverEvent.Found) {
188                 currentInfo = info;
189
190                 foreach (ServiceInfoHandler handler in foundListeners)
191                     handler (this, info);
192             } else {
193                 currentInfo = ServiceInfo.Zero;
194                 
195                 foreach (EventHandler handler in timeoutListeners)
196                     handler (this, new EventArgs ());
197             }
198         }
199     }
200 }