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