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 } 226