]> git.meshlink.io Git - catta/blob - avahi-sharp/ServiceResolver.cs
add some data access api to string list, and use it in ServiceResolver
[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
48         private ArrayList foundListeners = new ArrayList ();
49         private ArrayList timeoutListeners = new ArrayList ();
50         
51         [DllImport ("avahi-client")]
52         private static extern IntPtr avahi_service_resolver_new (IntPtr client, int iface, Protocol proto,
53                                                                  IntPtr name, IntPtr type, IntPtr domain,
54                                                                  Protocol aproto, ServiceResolverCallback cb,
55                                                                  IntPtr userdata);
56
57         [DllImport ("avahi-common")]
58         private static extern IntPtr avahi_string_list_get_next (IntPtr list);
59
60         [DllImport ("avahi-common")]
61         private static extern IntPtr avahi_string_list_get_text (IntPtr list);
62
63         [DllImport ("avahi-common")]
64         private static extern int avahi_string_list_get_size (IntPtr list);
65
66         [DllImport ("avahi-client")]
67         private static extern void avahi_service_resolver_free (IntPtr handle);
68
69         public event ServiceInfoHandler Found
70         {
71             add {
72                 foundListeners.Add (value);
73                 Start ();
74             }
75             remove {
76                 foundListeners.Remove (value);
77                 Stop (false);
78             }
79         }
80         
81         public event EventHandler Timeout
82         {
83             add {
84                 timeoutListeners.Add (value);
85                 Start ();
86             }
87             remove {
88                 timeoutListeners.Remove (value);
89                 Stop (false);
90             }
91         }
92
93         public ServiceInfo Service
94         {
95             get { return currentInfo; }
96         }
97
98         public ServiceResolver (Client client, string name, string type, string domain) : this (client, -1,
99                                                                                                 Protocol.Unspecified,
100                                                                                                 name, type, domain,
101                                                                                                 Protocol.Unspecified)
102         {
103         }
104
105         public ServiceResolver (Client client, ServiceInfo service) : this (client, service.NetworkInterface,
106                                                                             service.Protocol, service.Name,
107                                                                             service.ServiceType, service.Domain,
108                                                                             Protocol.Unspecified)
109         {
110         }
111         
112         public ServiceResolver (Client client, int iface, Protocol proto, string name,
113                                 string type, string domain, Protocol aproto)
114         {
115             this.client = client;
116             this.iface = iface;
117             this.proto = proto;
118             this.name = name;
119             this.type = type;
120             this.domain = domain;
121             this.aproto = aproto;
122             
123             
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, OnServiceResolverCallback, 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             ServiceInfo info;
165             info.NetworkInterface = iface;
166             info.Protocol = proto;
167             info.Domain = Utility.PtrToString (domain);
168             info.ServiceType = Utility.PtrToString (type);
169             info.Name = Utility.PtrToString (name);
170             info.Host = Utility.PtrToString (host);
171             info.Address = Utility.PtrToAddress (address);
172             info.Port = port;
173
174             ArrayList txtlist = new ArrayList ();
175             for (IntPtr l = txt; l != IntPtr.Zero; l = avahi_string_list_get_next (l)) {
176                 IntPtr buf = avahi_string_list_get_text (l);
177                 int len = avahi_string_list_get_size (l);
178
179                 byte[] txtbuf = new byte[len];
180                 Marshal.Copy (buf, txtbuf, 0, len);
181                 txtlist.Add (txtbuf);
182             }
183
184             info.Text = (byte[][]) txtlist.ToArray (typeof (byte[]));
185             
186             if (revent == ResolverEvent.Found) {
187                 currentInfo = info;
188
189                 foreach (ServiceInfoHandler handler in foundListeners)
190                     handler (this, info);
191             } else {
192                 currentInfo = ServiceInfo.Zero;
193                 
194                 foreach (EventHandler handler in timeoutListeners)
195                     handler (this, new EventArgs ());
196             }
197         }
198     }
199 }