]> git.meshlink.io Git - catta/blob - avahi-sharp/EntryGroup.cs
* Add EntryGroup.UpdateService, EntryGroup.AddServiceSubtype,
[catta] / avahi-sharp / EntryGroup.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.Net;
24 using System.Runtime.InteropServices;
25 using Mono.Unix;
26
27 namespace Avahi
28 {
29
30     [Flags]
31     public enum PublishFlags {
32         None = 0,
33         Unique = 1,
34         NoProbe = 2,
35         NoAnnounce = 4,
36         AllowMultiple = 8,
37         NoReverse = 16,
38         NoCookie = 32,
39         Update = 64,
40         UseWideArea = 128,
41         UseMulticast = 256
42     }
43     
44     public enum EntryGroupState {
45         Uncommited,
46         Registering,
47         Established,
48         Collision,
49         Failure
50     }
51
52     public class EntryGroupStateArgs : EventArgs
53     {
54         private EntryGroupState state;
55
56         public EntryGroupState State
57         {
58             get { return state; }
59         }
60         
61         public EntryGroupStateArgs (EntryGroupState state)
62         {
63             this.state = state;
64         }
65     }
66
67     internal delegate void EntryGroupCallback (IntPtr group, EntryGroupState state, IntPtr userdata);
68     public delegate void EntryGroupStateHandler (object o, EntryGroupStateArgs args);
69     
70     public class EntryGroup : IDisposable
71     {
72         private Client client;
73         private IntPtr handle;
74         private EntryGroupCallback cb;
75         
76         [DllImport ("avahi-client")]
77         private static extern IntPtr avahi_entry_group_new (IntPtr client, EntryGroupCallback cb, IntPtr userdata);
78
79         [DllImport ("avahi-client")]
80         private static extern int avahi_entry_group_commit (IntPtr group);
81
82         [DllImport ("avahi-client")]
83         private static extern int avahi_entry_group_reset (IntPtr group);
84
85         [DllImport ("avahi-client")]
86         private static extern EntryGroupState avahi_entry_group_get_state (IntPtr group);
87
88         [DllImport ("avahi-client")]
89         private static extern bool avahi_entry_group_is_empty (IntPtr group);
90
91         [DllImport ("avahi-client")]
92         private static extern int avahi_entry_group_add_service_strlst (IntPtr group, int iface, Protocol proto,
93                                                                         PublishFlags flags, IntPtr name, IntPtr type,
94                                                                         IntPtr domain, IntPtr host, UInt16 port,
95                                                                         IntPtr strlst);
96
97         [DllImport ("avahi-client")]
98         private static extern int avahi_entry_group_update_service_strlst (IntPtr group, int iface, Protocol proto,
99                                                                            PublishFlags flags, IntPtr name,
100                                                                            IntPtr type, IntPtr domain, IntPtr strlst);
101
102         [DllImport ("avahi-client")]
103         private static extern int avahi_entry_group_add_service_subtype (IntPtr group, int iface, Protocol proto,
104                                                                          PublishFlags flags, IntPtr name, IntPtr type,
105                                                                          IntPtr domain, IntPtr subtype);
106
107         [DllImport ("avahi-client")]
108         private static extern int avahi_entry_group_add_address (IntPtr group, int iface, Protocol proto,
109                                                                  PublishFlags flags, IntPtr name, IntPtr address);
110
111
112         [DllImport ("avahi-client")]
113         private static extern int avahi_entry_group_add_record (IntPtr group, int iface, Protocol proto,
114                                                                 PublishFlags flags, IntPtr name, RecordClass clazz,
115                                                                 RecordType type, uint ttl, byte[] rdata, int size);
116         
117         [DllImport ("avahi-client")]
118         private static extern void avahi_entry_group_free (IntPtr group);
119
120         [DllImport ("avahi-common")]
121         private static extern IntPtr avahi_string_list_new (IntPtr txt);
122
123         [DllImport ("avahi-common")]
124         private static extern IntPtr avahi_string_list_add (IntPtr list, IntPtr txt);
125
126         [DllImport ("avahi-common")]
127         private static extern void avahi_string_list_free (IntPtr list);
128
129         [DllImport ("avahi-common")]
130         private static extern int avahi_service_name_join (IntPtr buf, int len, IntPtr name, IntPtr type,
131                                                            IntPtr domain);
132
133         [DllImport ("avahi-common")]
134         private static extern int avahi_service_name_split (IntPtr service, IntPtr name, int name_len,
135                                                             IntPtr type, int type_len,
136                                                             IntPtr domain, int domain_len);
137
138         
139         [DllImport ("avahi-common")]
140         private static extern IntPtr avahi_alternative_service_name (IntPtr name);
141
142         public event EntryGroupStateHandler StateChanged;
143         
144         public EntryGroupState State
145         {
146             get {
147                 lock (client) {
148                     return avahi_entry_group_get_state (handle);
149                 }
150             }
151         }
152
153         public bool IsEmpty
154         {
155             get {
156                 lock (client) {
157                     return avahi_entry_group_is_empty (handle);
158                 }
159             }
160         }
161         
162         public EntryGroup (Client client)
163         {
164             this.client = client;
165             cb = OnEntryGroupCallback;
166
167             lock (client) {
168                 handle = avahi_entry_group_new (client.Handle, cb, IntPtr.Zero);
169                 if (handle == IntPtr.Zero)
170                     client.ThrowError ();
171             }
172         }
173
174         ~EntryGroup ()
175         {
176             Dispose ();
177         }
178
179         public void Dispose ()
180         {
181             if (client.Handle != IntPtr.Zero && handle != IntPtr.Zero) {
182                 lock (client) {
183                     avahi_entry_group_free (handle);
184                     handle = IntPtr.Zero;
185                 }
186             }
187         }
188
189         public void Commit ()
190         {
191             lock (client) {
192                 if (avahi_entry_group_commit (handle) < 0)
193                     client.ThrowError ();
194             }
195         }
196
197         public void Reset ()
198         {
199             lock (client) {
200                 if (avahi_entry_group_reset (handle) < 0)
201                     client.ThrowError ();
202             }
203         }
204
205         public void AddService (string name, string type, string domain,
206                                 UInt16 port, params string[] txt)
207         {
208             AddService (PublishFlags.None, name, type, domain, port, txt);
209         }
210
211         public void AddService (PublishFlags flags, string name, string type, string domain,
212                                 UInt16 port, params string[] txt)
213         {
214             AddService (-1, Protocol.Unspecified, flags, name, type, domain, null, port, txt);
215         }
216
217         public void AddService (int iface, Protocol proto, PublishFlags flags, string name, string type, string domain,
218                                 string host, UInt16 port, params string[] txt)
219         {
220             IntPtr list = avahi_string_list_new (IntPtr.Zero);
221
222             if (txt != null) {
223                 foreach (string item in txt) {
224                     IntPtr itemPtr = Utility.StringToPtr (item);
225                     list = avahi_string_list_add (list, itemPtr);
226                     Utility.Free (itemPtr);
227                 }
228             }
229
230             IntPtr namePtr = Utility.StringToPtr (name);
231             IntPtr typePtr = Utility.StringToPtr (type);
232             IntPtr domainPtr = Utility.StringToPtr (domain);
233             IntPtr hostPtr = Utility.StringToPtr (host);
234
235             lock (client) {
236                 int ret = avahi_entry_group_add_service_strlst (handle, iface, proto, flags, namePtr, typePtr, domainPtr,
237                                                                 hostPtr, port, list);
238
239                 Utility.Free (namePtr);
240                 Utility.Free (typePtr);
241                 Utility.Free (domainPtr);
242                 Utility.Free (hostPtr);
243                 avahi_string_list_free (list);
244
245                 if (ret < 0) {
246                     client.ThrowError ();
247                 }
248             }
249             
250         }
251
252         public void UpdateService (string name, string type, string domain, params string[] txt)
253         {
254             UpdateService (-1, Protocol.Unspecified, PublishFlags.None, name, type, domain, txt);
255         }
256
257         public void UpdateService (int iface, Protocol proto, PublishFlags flags, string name, string type,
258                                    string domain, params string[] txt)
259         {
260             IntPtr list = avahi_string_list_new (IntPtr.Zero);
261
262             if (txt != null) {
263                 foreach (string item in txt) {
264                     IntPtr itemPtr = Utility.StringToPtr (item);
265                     list = avahi_string_list_add (list, itemPtr);
266                     Utility.Free (itemPtr);
267                 }
268             }
269
270             IntPtr namePtr = Utility.StringToPtr (name);
271             IntPtr typePtr = Utility.StringToPtr (type);
272             IntPtr domainPtr = Utility.StringToPtr (domain);
273
274             lock (client) {
275                 int ret = avahi_entry_group_update_service_strlst (handle, iface, proto, flags, namePtr, typePtr, domainPtr, list);
276
277                 Utility.Free (namePtr);
278                 Utility.Free (typePtr);
279                 Utility.Free (domainPtr);
280                 
281                 avahi_string_list_free (list);
282
283                 if (ret < 0) {
284                     client.ThrowError ();
285                 }
286             }
287         }
288
289         public void AddServiceSubtype (string name, string type, string domain, string subtype)
290         {
291             AddServiceSubtype (-1, Protocol.Unspecified, PublishFlags.None, name, type, domain, subtype);
292         }
293
294         public void AddServiceSubtype (int iface, Protocol proto, PublishFlags flags, string name,
295                                        string type, string domain, string subtype)
296         {
297             IntPtr namePtr = Utility.StringToPtr (name);
298             IntPtr typePtr = Utility.StringToPtr (type);
299             IntPtr domainPtr = Utility.StringToPtr (domain);
300             IntPtr subtypePtr = Utility.StringToPtr (subtype);
301
302             lock (client) {
303                 int ret = avahi_entry_group_add_service_subtype (handle, iface, proto, flags, namePtr,
304                                                                  typePtr, domainPtr, subtypePtr);
305
306                 Utility.Free (namePtr);
307                 Utility.Free (typePtr);
308                 Utility.Free (domainPtr);
309                 Utility.Free (subtypePtr);
310                 
311                 if (ret < 0) {
312                     client.ThrowError ();
313                 }
314             }
315         }
316
317         public void AddAddress (string name, IPAddress address)
318         {
319             AddAddress (-1, Protocol.Unspecified, PublishFlags.None, name, address);
320         }
321
322         public void AddAddress (int iface, Protocol proto, PublishFlags flags, string name, IPAddress address)
323         {
324             IntPtr namePtr = Utility.StringToPtr (name);
325             IntPtr addressPtr = Utility.AddressToPtr (address);
326
327             lock (client) {
328                 int ret = avahi_entry_group_add_address (handle, iface, proto, flags, namePtr, addressPtr);
329
330                 Utility.Free (namePtr);
331                 Utility.Free (addressPtr);
332
333                 if (ret < 0) {
334                     client.ThrowError ();
335                 }
336             }
337         }
338
339         public void AddRecord (string name, RecordClass clazz, RecordType type, uint ttl, byte[] rdata, int length)
340         {
341             AddRecord (-1, Protocol.Unspecified, PublishFlags.None, name, clazz, type, ttl, rdata, length);
342         }
343
344         public void AddRecord (int iface, Protocol proto, PublishFlags flags, string name,
345                                RecordClass clazz, RecordType type, uint ttl, byte[] rdata, int length)
346         {
347             IntPtr namePtr = Utility.StringToPtr (name);
348
349             lock (client) {
350                 int ret = avahi_entry_group_add_record (handle, iface, proto, flags, namePtr,
351                                                         clazz, type, ttl, rdata, length);
352
353                 Utility.Free (namePtr);
354                 
355                 if (ret < 0) {
356                     client.ThrowError ();
357                 }
358             }
359         }
360
361         public static string JoinServiceName (string name, string type, string domain)
362         {
363             int len = 4 * (name.Length + type.Length + domain.Length) + 4;
364             IntPtr buf = Stdlib.malloc ((ulong) len);
365
366             IntPtr namePtr = Utility.StringToPtr (name);
367             IntPtr typePtr = Utility.StringToPtr (type);
368             IntPtr domainPtr = Utility.StringToPtr (domain);
369
370             int ret = avahi_service_name_join (buf, len, namePtr, typePtr, domainPtr);
371
372             Utility.Free (namePtr);
373             Utility.Free (typePtr);
374             Utility.Free (domainPtr);
375
376             if (ret < 0) {
377                 Utility.Free (buf);
378                 return null; // FIXME, should throw exception
379             }
380
381             string service = Utility.PtrToString (buf);
382             Utility.Free (buf);
383
384             return service;
385         }
386
387         public static void SplitServiceName (string service, out string name, out string type, out string domain)
388         {
389             int len = 1024;
390
391             IntPtr servicePtr = Utility.StringToPtr (service);
392             IntPtr namePtr = Stdlib.malloc ((ulong) len);
393             IntPtr typePtr = Stdlib.malloc ((ulong) len);
394             IntPtr domainPtr = Stdlib.malloc ((ulong) len);
395             
396             int ret = avahi_service_name_split (servicePtr, namePtr, len, typePtr, len, domainPtr, len);
397
398             Utility.Free (servicePtr);
399             
400             if (ret < 0) {
401                 Utility.Free (namePtr);
402                 Utility.Free (typePtr);
403                 Utility.Free (domainPtr);
404                 
405                 name = null;
406                 type = null;
407                 domain = null;
408                 return;
409             }
410
411             name = Utility.PtrToString (namePtr);
412             type = Utility.PtrToString (typePtr);
413             domain = Utility.PtrToString (domainPtr);
414
415             Utility.Free (namePtr);
416             Utility.Free (typePtr);
417             Utility.Free (domainPtr);
418         }
419
420         public static string GetAlternativeServiceName (string name) {
421             IntPtr namePtr = Utility.StringToPtr (name);
422             IntPtr result = avahi_alternative_service_name (namePtr);
423             Utility.Free (namePtr);
424
425             return Utility.PtrToStringFree (result);
426         }
427
428         private void OnEntryGroupCallback (IntPtr group, EntryGroupState state, IntPtr userdata)
429         {
430             if (StateChanged != null)
431                 StateChanged (this, new EntryGroupStateArgs (state));
432         }
433     }
434 }