• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
RecordInfoHandler(object o, RecordInfoArgs args)29     public delegate void RecordInfoHandler (object o, RecordInfoArgs args);
30 
RecordBrowserCallback(IntPtr browser, int iface, Protocol proto, BrowserEvent bevent, IntPtr name, ushort clazz, ushort type, IntPtr rdata, int size, LookupResultFlags flags, IntPtr userdata)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 
RecordInfoArgs(RecordInfo record)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")]
avahi_record_browser_new(IntPtr client, int iface, Protocol proto, byte[] name, ushort clazz, ushort type, LookupFlags flags, RecordBrowserCallback cb, IntPtr userdata)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")]
avahi_record_browser_free(IntPtr handle)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 
RecordBrowser(Client client, string name, RecordType type)132         public RecordBrowser (Client client, string name, RecordType type) :
133             this (client, -1, Protocol.Unspecified, name, RecordClass.In, type, LookupFlags.None)
134         {
135         }
136 
RecordBrowser(Client client, int iface, Protocol proto, string name, RecordClass clazz, RecordType type, LookupFlags flags)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 
~RecordBrowser()150         ~RecordBrowser ()
151         {
152             Dispose ();
153         }
154 
Dispose()155         public void Dispose ()
156         {
157             Stop (true);
158         }
159 
Start()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 
Stop(bool force)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 
OnRecordBrowserCallback(IntPtr browser, int iface, Protocol proto, BrowserEvent bevent, IntPtr name, ushort clazz, ushort type, IntPtr rdata, int size, LookupResultFlags flags, IntPtr userdata)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 }
226