]> git.meshlink.io Git - catta/blob - avahi-sharp/RecordBrowser.cs
fix avahi_netlink_new to allow multiple netlinks per process
[catta] / avahi-sharp / RecordBrowser.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.Net;
22 using System.Collections;
23 using System.Runtime.InteropServices;
24 using System.Text;
25
26 namespace Avahi
27 {
28
29     public delegate void RecordInfoHandler (object o, RecordInfoArgs args);
30
31     internal delegate void RecordBrowserCallback (IntPtr browser, int iface, Protocol proto, BrowserEvent bevent,
32                                                   IntPtr name, ushort clazz, ushort type, IntPtr rdata, int size,
33                                                   LookupResultFlags flags, IntPtr userdata);
34
35     public enum RecordClass {
36         In = 1
37     }
38
39     public enum RecordType {
40         A = 1,
41         Ns = 2,
42         Cname = 5,
43         Soa = 6,
44         Ptr = 12,
45         Hinfo = 13,
46         Mx = 15,
47         Txt = 16,
48         Aaa = 28,
49         Srv = 33
50     }
51
52     public struct RecordInfo
53     {
54         public int NetworkInterface;
55         public Protocol Protocol;
56         public string Name;
57         public RecordClass Class;
58         public RecordType Type;
59         public byte[] Data;
60         public LookupResultFlags Flags;
61     }
62
63     public class RecordInfoArgs : EventArgs
64     {
65         private RecordInfo record;
66
67         public RecordInfo Record {
68             get { return record; }
69         }
70
71         public RecordInfoArgs (RecordInfo record)
72         {
73             this.record = record;
74         }
75     }
76
77     public class RecordBrowser : BrowserBase, IDisposable
78     {
79         private IntPtr handle;
80         private ArrayList infos = new ArrayList ();
81         private Client client;
82         private int iface;
83         private Protocol proto;
84         private string name;
85         private RecordClass clazz;
86         private RecordType type;
87         private LookupFlags flags;
88         private RecordBrowserCallback cb;
89
90         private ArrayList addListeners = new ArrayList ();
91         private ArrayList removeListeners = new ArrayList ();
92
93         [DllImport ("avahi-client")]
94         private static extern IntPtr avahi_record_browser_new (IntPtr client, int iface, Protocol proto,
95                                                                byte[] name, ushort clazz, ushort type,
96                                                                LookupFlags flags, RecordBrowserCallback cb,
97                                                                IntPtr userdata);
98
99
100         [DllImport ("avahi-client")]
101         private static extern void avahi_record_browser_free (IntPtr handle);
102
103         public event RecordInfoHandler RecordAdded
104         {
105             add {
106                 addListeners.Add (value);
107                 Start ();
108             }
109             remove {
110                 addListeners.Remove (value);
111                 Stop (false);
112             }
113         }
114
115         public event RecordInfoHandler RecordRemoved
116         {
117             add {
118                 removeListeners.Add (value);
119                 Start ();
120             }
121             remove {
122                 removeListeners.Remove (value);
123                 Stop (false);
124             }
125         }
126
127         public RecordInfo[] Records
128         {
129             get { return (RecordInfo[]) infos.ToArray (typeof (RecordInfo)); }
130         }
131
132         public RecordBrowser (Client client, string name, RecordType type) :
133             this (client, -1, Protocol.Unspecified, name, RecordClass.In, type, LookupFlags.None)
134         {
135         }
136
137         public RecordBrowser (Client client, int iface, Protocol proto, string name, RecordClass clazz,
138                               RecordType type, LookupFlags flags)
139         {
140             this.client = client;
141             this.iface = iface;
142             this.proto = proto;
143             this.name = name;
144             this.clazz = clazz;
145             this.type = type;
146             this.flags = flags;
147             cb = OnRecordBrowserCallback;
148         }
149
150         ~RecordBrowser ()
151         {
152             Dispose ();
153         }
154
155         public void Dispose ()
156         {
157             Stop (true);
158         }
159
160         private void Start ()
161         {
162             if (client.Handle == IntPtr.Zero || handle != IntPtr.Zero ||
163                 (addListeners.Count == 0 && removeListeners.Count == 0))
164                 return;
165
166             lock (client) {
167                 handle = avahi_record_browser_new (client.Handle, iface, proto, Utility.StringToBytes (name),
168                                                    (ushort) clazz, (ushort) type, flags, cb, IntPtr.Zero);
169
170                 if (handle == IntPtr.Zero)
171                     client.ThrowError ();
172             }
173         }
174
175         private void Stop (bool force)
176         {
177             if (client.Handle != IntPtr.Zero && handle != IntPtr.Zero &&
178                 (force || (addListeners.Count == 0 && removeListeners.Count == 0))) {
179
180                 lock (client) {
181                     avahi_record_browser_free (handle);
182                     handle = IntPtr.Zero;
183                 }
184             }
185         }
186
187         private void OnRecordBrowserCallback (IntPtr browser, int iface, Protocol proto, BrowserEvent bevent,
188                                               IntPtr name, ushort clazz, ushort type, IntPtr rdata, int size,
189                                               LookupResultFlags flags, IntPtr userdata)
190         {
191             RecordInfo info;
192             info.NetworkInterface = iface;
193             info.Protocol = proto;
194             info.Name = Utility.PtrToString (name);
195             info.Class = (RecordClass) clazz;
196             info.Type = (RecordType) type;
197             info.Flags = flags;
198             info.Data = new byte[size];
199
200             if (rdata != IntPtr.Zero) {
201                 Marshal.Copy (rdata, info.Data, 0, size);
202             }
203
204             switch (bevent) {
205             case BrowserEvent.Added:
206                 infos.Add (info);
207
208                 foreach (RecordInfoHandler handler in addListeners)
209                     handler (this, new RecordInfoArgs (info));
210
211                 break;
212             case BrowserEvent.Removed:
213                 infos.Remove (info);
214
215                 foreach (RecordInfoHandler handler in removeListeners)
216                     handler (this, new RecordInfoArgs (info));
217
218                 break;
219             default:
220                 EmitBrowserEvent (bevent);
221                 break;
222             }
223         }
224     }
225 }