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