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