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