1/* $Id$ */ 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 internal delegate void ServiceBrowserCallback (IntPtr browser, int iface, Protocol proto, BrowserEvent bevent, 31 IntPtr name, IntPtr type, IntPtr domain, LookupResultFlags flags, 32 IntPtr userdata); 33 34 public struct ServiceInfo 35 { 36 public int NetworkInterface; 37 public Protocol Protocol; 38 public string Domain; 39 public string ServiceType; 40 public string Name; 41 42 public string HostName; 43 public IPAddress Address; 44 public UInt16 Port; 45 public byte[][] Text; 46 public LookupResultFlags Flags; 47 48 public static ServiceInfo Zero = new ServiceInfo (); 49 } 50 51 public class ServiceInfoArgs : EventArgs 52 { 53 private ServiceInfo service; 54 55 public ServiceInfo Service { 56 get { return service; } 57 } 58 59 public ServiceInfoArgs (ServiceInfo service) 60 { 61 this.service = service; 62 } 63 } 64 65 public delegate void ServiceInfoHandler (object o, ServiceInfoArgs args); 66 67 public class ServiceBrowser : BrowserBase, IDisposable 68 { 69 private IntPtr handle; 70 private ArrayList infos = new ArrayList (); 71 private Client client; 72 private int iface; 73 private Protocol proto; 74 private string domain; 75 private string type; 76 private LookupFlags flags; 77 private ServiceBrowserCallback cb; 78 79 private ArrayList addListeners = new ArrayList (); 80 private ArrayList removeListeners = new ArrayList (); 81 82 [DllImport ("avahi-client")] 83 private static extern IntPtr avahi_service_browser_new (IntPtr client, int iface, int proto, byte[] type, 84 byte[] domain, LookupFlags flags, 85 ServiceBrowserCallback cb, 86 IntPtr userdata); 87 88 [DllImport ("avahi-client")] 89 private static extern void avahi_service_browser_free (IntPtr handle); 90 91 public event ServiceInfoHandler ServiceAdded 92 { 93 add { 94 addListeners.Add (value); 95 Start (); 96 } 97 remove { 98 addListeners.Remove (value); 99 Stop (false); 100 } 101 } 102 103 public event ServiceInfoHandler ServiceRemoved 104 { 105 add { 106 removeListeners.Add (value); 107 Start (); 108 } 109 remove { 110 removeListeners.Remove (value); 111 Stop (false); 112 } 113 } 114 115 public ServiceInfo[] Services 116 { 117 get { return (ServiceInfo[]) infos.ToArray (typeof (ServiceInfo)); } 118 } 119 120 public ServiceBrowser (Client client, string type) : this (client, type, client.DomainName) 121 { 122 } 123 124 public ServiceBrowser (Client client, string type, string domain) : this (client, -1, Protocol.Unspecified, 125 type, domain, LookupFlags.None) 126 { 127 } 128 129 public ServiceBrowser (Client client, int iface, Protocol proto, string type, string domain, LookupFlags flags) 130 { 131 this.client = client; 132 this.iface = iface; 133 this.proto = proto; 134 this.domain = domain; 135 this.type = type; 136 this.flags = flags; 137 cb = OnServiceBrowserCallback; 138 } 139 140 ~ServiceBrowser () 141 { 142 Dispose (); 143 } 144 145 public void Dispose () 146 { 147 Stop (true); 148 } 149 150 private void Start () 151 { 152 if (client.Handle == IntPtr.Zero || handle != IntPtr.Zero || 153 (addListeners.Count == 0 && removeListeners.Count == 0)) 154 return; 155 156 lock (client) { 157 handle = avahi_service_browser_new (client.Handle, iface, (int) proto, 158 Utility.StringToBytes (type), Utility.StringToBytes (domain), 159 flags, cb, IntPtr.Zero); 160 161 if (handle == IntPtr.Zero) 162 client.ThrowError (); 163 } 164 } 165 166 private void Stop (bool force) 167 { 168 if (client.Handle != IntPtr.Zero && handle != IntPtr.Zero && 169 (force || (addListeners.Count == 0 && removeListeners.Count == 0))) { 170 171 lock (client) { 172 avahi_service_browser_free (handle); 173 handle = IntPtr.Zero; 174 } 175 } 176 } 177 178 private void OnServiceBrowserCallback (IntPtr browser, int iface, Protocol proto, BrowserEvent bevent, 179 IntPtr name, IntPtr type, IntPtr domain, LookupResultFlags flags, 180 IntPtr userdata) 181 { 182 183 ServiceInfo info; 184 info.NetworkInterface = iface; 185 info.Protocol = proto; 186 info.Domain = Utility.PtrToString (domain); 187 info.ServiceType = Utility.PtrToString (type); 188 info.Name = Utility.PtrToString (name); 189 info.HostName = null; 190 info.Address = null; 191 info.Port = 0; 192 info.Text = null; 193 info.Flags = flags; 194 195 switch (bevent) { 196 case BrowserEvent.Added: 197 infos.Add (info); 198 199 foreach (ServiceInfoHandler handler in addListeners) 200 handler (this, new ServiceInfoArgs (info)); 201 202 break; 203 case BrowserEvent.Removed: 204 infos.Remove (info); 205 206 foreach (ServiceInfoHandler handler in removeListeners) 207 handler (this, new ServiceInfoArgs (info)); 208 209 break; 210 default: 211 EmitBrowserEvent (bevent); 212 break; 213 } 214 } 215 } 216} 217