1 // /Copyright 2003-2005 Arthur van Hoff, Rick Blair 2 // Licensed under Apache License version 2.0 3 // Original license LGPL 4 5 package javax.jmdns; 6 7 import java.io.Closeable; 8 import java.io.IOException; 9 import java.net.InetAddress; 10 import java.util.Collection; 11 import java.util.Map; 12 13 import javax.jmdns.impl.JmDNSImpl; 14 15 /** 16 * mDNS implementation in Java. 17 * 18 * @author Arthur van Hoff, Rick Blair, Jeff Sonstein, Werner Randelshofer, Pierre Frisch, Scott Lewis, Scott Cytacki 19 */ 20 public abstract class JmDNS implements Closeable { 21 22 /** 23 * 24 */ 25 public static interface Delegate { 26 27 /** 28 * This method is called if JmDNS cannot recover from an I/O error. 29 * 30 * @param dns 31 * target DNS 32 * @param infos 33 * service info registered with the DNS 34 */ cannotRecoverFromIOError(JmDNS dns, Collection<ServiceInfo> infos)35 public void cannotRecoverFromIOError(JmDNS dns, Collection<ServiceInfo> infos); 36 37 } 38 39 /** 40 * The version of JmDNS. 41 */ 42 public static final String VERSION = "3.4.2"; 43 44 /** 45 * <p> 46 * Create an instance of JmDNS. 47 * </p> 48 * <p> 49 * <b>Note:</b> This is a convenience method. The preferred constructor is {@link #create(InetAddress, String)}.<br/> 50 * Check that your platform correctly handle the default localhost IP address and the local hostname. In doubt use the explicit constructor.<br/> 51 * This call is equivalent to <code>create(null, null)</code>. 52 * </p> 53 * 54 * @see #create(InetAddress, String) 55 * @return jmDNS instance 56 * @exception IOException 57 * if an exception occurs during the socket creation 58 */ create()59 public static JmDNS create() throws IOException { 60 return new JmDNSImpl(null, null); 61 } 62 63 /** 64 * <p> 65 * Create an instance of JmDNS and bind it to a specific network interface given its IP-address. 66 * </p> 67 * <p> 68 * <b>Note:</b> This is a convenience method. The preferred constructor is {@link #create(InetAddress, String)}.<br/> 69 * Check that your platform correctly handle the default localhost IP address and the local hostname. In doubt use the explicit constructor.<br/> 70 * This call is equivalent to <code>create(addr, null)</code>. 71 * </p> 72 * 73 * @see #create(InetAddress, String) 74 * @param addr 75 * IP address to bind to. 76 * @return jmDNS instance 77 * @exception IOException 78 * if an exception occurs during the socket creation 79 */ create(final InetAddress addr)80 public static JmDNS create(final InetAddress addr) throws IOException { 81 return new JmDNSImpl(addr, null); 82 } 83 84 /** 85 * <p> 86 * Create an instance of JmDNS. 87 * </p> 88 * <p> 89 * <b>Note:</b> This is a convenience method. The preferred constructor is {@link #create(InetAddress, String)}.<br/> 90 * Check that your platform correctly handle the default localhost IP address and the local hostname. In doubt use the explicit constructor.<br/> 91 * This call is equivalent to <code>create(null, name)</code>. 92 * </p> 93 * 94 * @see #create(InetAddress, String) 95 * @param name 96 * name of the newly created JmDNS 97 * @return jmDNS instance 98 * @exception IOException 99 * if an exception occurs during the socket creation 100 */ create(final String name)101 public static JmDNS create(final String name) throws IOException { 102 return new JmDNSImpl(null, name); 103 } 104 105 /** 106 * <p> 107 * Create an instance of JmDNS and bind it to a specific network interface given its IP-address. 108 * </p> 109 * If <code>addr</code> parameter is null this method will try to resolve to a local IP address of the machine using a network discovery: 110 * <ol> 111 * <li>Check the system property <code>net.mdns.interface</code></li> 112 * <li>Check the JVM local host</li> 113 * <li>Use the {@link NetworkTopologyDiscovery} to find a valid network interface and IP.</li> 114 * <li>In the last resort bind to the loopback address. This is non functional in most cases.</li> 115 * </ol> 116 * If <code>name</code> parameter is null will use the hostname. The hostname is determined by the following algorithm: 117 * <ol> 118 * <li>Get the hostname from the InetAdress obtained before.</li> 119 * <li>If the hostname is a reverse lookup default to <code>JmDNS name</code> or <code>computer</code> if null.</li> 120 * <li>If the name contains <code>'.'</code> replace them by <code>'-'</code></li> 121 * <li>Add <code>.local.</code> at the end of the name.</li> 122 * </ol> 123 * <p> 124 * <b>Note:</b> If you need to use a custom {@link NetworkTopologyDiscovery} it must be setup before any call to this method. This is done by setting up a {@link NetworkTopologyDiscovery.Factory.ClassDelegate} and installing it using 125 * {@link NetworkTopologyDiscovery.Factory#setClassDelegate(NetworkTopologyDiscovery.Factory.ClassDelegate)}. This must be done before creating a {@link JmDNS} or {@link JmmDNS} instance. 126 * </p> 127 * 128 * @param addr 129 * IP address to bind to. 130 * @param name 131 * name of the newly created JmDNS 132 * @return jmDNS instance 133 * @exception IOException 134 * if an exception occurs during the socket creation 135 */ create(final InetAddress addr, final String name)136 public static JmDNS create(final InetAddress addr, final String name) throws IOException { 137 return new JmDNSImpl(addr, name); 138 } 139 140 /** 141 * Return the name of the JmDNS instance. This is an arbitrary string that is useful for distinguishing instances. 142 * 143 * @return name of the JmDNS 144 */ getName()145 public abstract String getName(); 146 147 /** 148 * Return the HostName associated with this JmDNS instance. Note: May not be the same as what started. The host name is subject to negotiation. 149 * 150 * @return Host name 151 */ getHostName()152 public abstract String getHostName(); 153 154 /** 155 * Return the address of the interface to which this instance of JmDNS is bound. 156 * 157 * @return Internet Address 158 * @exception IOException 159 * if there is an error in the underlying protocol, such as a TCP error. 160 */ getInetAddress()161 public abstract InetAddress getInetAddress() throws IOException; 162 163 /** 164 * Return the address of the interface to which this instance of JmDNS is bound. 165 * 166 * @return Internet Address 167 * @exception IOException 168 * if there is an error in the underlying protocol, such as a TCP error. 169 * @deprecated do not use this implementation yields unpredictable results use {@link #getInetAddress()} 170 */ 171 @Deprecated getInterface()172 public abstract InetAddress getInterface() throws IOException; 173 174 /** 175 * Get service information. If the information is not cached, the method will block until updated information is received. 176 * <p/> 177 * Usage note: Do not call this method from the AWT event dispatcher thread. You will make the user interface unresponsive. 178 * 179 * @param type 180 * fully qualified service type, such as <code>_http._tcp.local.</code> . 181 * @param name 182 * unqualified service name, such as <code>foobar</code> . 183 * @return null if the service information cannot be obtained 184 */ getServiceInfo(String type, String name)185 public abstract ServiceInfo getServiceInfo(String type, String name); 186 187 /** 188 * Get service information. If the information is not cached, the method will block for the given timeout until updated information is received. 189 * <p/> 190 * Usage note: If you call this method from the AWT event dispatcher thread, use a small timeout, or you will make the user interface unresponsive. 191 * 192 * @param type 193 * full qualified service type, such as <code>_http._tcp.local.</code> . 194 * @param name 195 * unqualified service name, such as <code>foobar</code> . 196 * @param timeout 197 * timeout in milliseconds. Typical timeout should be 5s. 198 * @return null if the service information cannot be obtained 199 */ getServiceInfo(String type, String name, long timeout)200 public abstract ServiceInfo getServiceInfo(String type, String name, long timeout); 201 202 /** 203 * Get service information. If the information is not cached, the method will block until updated information is received. 204 * <p/> 205 * Usage note: Do not call this method from the AWT event dispatcher thread. You will make the user interface unresponsive. 206 * 207 * @param type 208 * fully qualified service type, such as <code>_http._tcp.local.</code> . 209 * @param name 210 * unqualified service name, such as <code>foobar</code> . 211 * @param persistent 212 * if <code>true</code> ServiceListener.resolveService will be called whenever new new information is received. 213 * @return null if the service information cannot be obtained 214 */ getServiceInfo(String type, String name, boolean persistent)215 public abstract ServiceInfo getServiceInfo(String type, String name, boolean persistent); 216 217 /** 218 * Get service information. If the information is not cached, the method will block for the given timeout until updated information is received. 219 * <p/> 220 * Usage note: If you call this method from the AWT event dispatcher thread, use a small timeout, or you will make the user interface unresponsive. 221 * 222 * @param type 223 * full qualified service type, such as <code>_http._tcp.local.</code> . 224 * @param name 225 * unqualified service name, such as <code>foobar</code> . 226 * @param timeout 227 * timeout in milliseconds. Typical timeout should be 5s. 228 * @param persistent 229 * if <code>true</code> ServiceListener.resolveService will be called whenever new new information is received. 230 * @return null if the service information cannot be obtained 231 */ getServiceInfo(String type, String name, boolean persistent, long timeout)232 public abstract ServiceInfo getServiceInfo(String type, String name, boolean persistent, long timeout); 233 234 /** 235 * Request service information. The information about the service is requested and the ServiceListener.resolveService method is called as soon as it is available. 236 * <p/> 237 * Usage note: Do not call this method from the AWT event dispatcher thread. You will make the user interface unresponsive. 238 * 239 * @param type 240 * full qualified service type, such as <code>_http._tcp.local.</code> . 241 * @param name 242 * unqualified service name, such as <code>foobar</code> . 243 */ requestServiceInfo(String type, String name)244 public abstract void requestServiceInfo(String type, String name); 245 246 /** 247 * Request service information. The information about the service is requested and the ServiceListener.resolveService method is called as soon as it is available. 248 * <p/> 249 * Usage note: Do not call this method from the AWT event dispatcher thread. You will make the user interface unresponsive. 250 * 251 * @param type 252 * full qualified service type, such as <code>_http._tcp.local.</code> . 253 * @param name 254 * unqualified service name, such as <code>foobar</code> . 255 * @param persistent 256 * if <code>true</code> ServiceListener.resolveService will be called whenever new new information is received. 257 */ requestServiceInfo(String type, String name, boolean persistent)258 public abstract void requestServiceInfo(String type, String name, boolean persistent); 259 260 /** 261 * Request service information. The information about the service is requested and the ServiceListener.resolveService method is called as soon as it is available. 262 * 263 * @param type 264 * full qualified service type, such as <code>_http._tcp.local.</code> . 265 * @param name 266 * unqualified service name, such as <code>foobar</code> . 267 * @param timeout 268 * timeout in milliseconds 269 */ requestServiceInfo(String type, String name, long timeout)270 public abstract void requestServiceInfo(String type, String name, long timeout); 271 272 /** 273 * Request service information. The information about the service is requested and the ServiceListener.resolveService method is called as soon as it is available. 274 * 275 * @param type 276 * full qualified service type, such as <code>_http._tcp.local.</code> . 277 * @param name 278 * unqualified service name, such as <code>foobar</code> . 279 * @param persistent 280 * if <code>true</code> ServiceListener.resolveService will be called whenever new new information is received. 281 * @param timeout 282 * timeout in milliseconds 283 */ requestServiceInfo(String type, String name, boolean persistent, long timeout)284 public abstract void requestServiceInfo(String type, String name, boolean persistent, long timeout); 285 286 /** 287 * Listen for service types. 288 * 289 * @param listener 290 * listener for service types 291 * @exception IOException 292 * if there is an error in the underlying protocol, such as a TCP error. 293 */ addServiceTypeListener(ServiceTypeListener listener)294 public abstract void addServiceTypeListener(ServiceTypeListener listener) throws IOException; 295 296 /** 297 * Remove listener for service types. 298 * 299 * @param listener 300 * listener for service types 301 */ removeServiceTypeListener(ServiceTypeListener listener)302 public abstract void removeServiceTypeListener(ServiceTypeListener listener); 303 304 /** 305 * Listen for services of a given type. The type has to be a fully qualified type name such as <code>_http._tcp.local.</code>. 306 * 307 * @param type 308 * full qualified service type, such as <code>_http._tcp.local.</code>. 309 * @param listener 310 * listener for service updates 311 */ addServiceListener(String type, ServiceListener listener)312 public abstract void addServiceListener(String type, ServiceListener listener); 313 314 /** 315 * Remove listener for services of a given type. 316 * 317 * @param type 318 * full qualified service type, such as <code>_http._tcp.local.</code>. 319 * @param listener 320 * listener for service updates 321 */ removeServiceListener(String type, ServiceListener listener)322 public abstract void removeServiceListener(String type, ServiceListener listener); 323 324 /** 325 * Register a service. The service is registered for access by other jmdns clients. The name of the service may be changed to make it unique.<br> 326 * Note that the given {@code ServiceInfo} is bound to this {@code JmDNS} instance, and should not be reused for any other {@linkplain #registerService(ServiceInfo)}. 327 * 328 * @param info 329 * service info to register 330 * @exception IOException 331 * if there is an error in the underlying protocol, such as a TCP error. 332 */ registerService(ServiceInfo info)333 public abstract void registerService(ServiceInfo info) throws IOException; 334 335 /** 336 * Unregister a service. The service should have been registered. 337 * <p> 338 * <b>Note:</b> Unregistered services will not disappear form the list of services immediately. According to the specification, when unregistering services we send goodbye packets and then wait <b>1s</b> before purging the cache.<br/> 339 * This is support for shared records that can be rescued by some other cooperation DNS. 340 * 341 * <pre> 342 * Clients receiving a Multicast DNS Response with a TTL of zero SHOULD NOT immediately delete the record from the cache, but instead record a TTL of 1 and then delete the record one second later. 343 * </pre> 344 * 345 * </p> 346 * 347 * @param info 348 * service info to remove 349 */ unregisterService(ServiceInfo info)350 public abstract void unregisterService(ServiceInfo info); 351 352 /** 353 * Unregister all services. 354 */ unregisterAllServices()355 public abstract void unregisterAllServices(); 356 357 /** 358 * Register a service type. If this service type was not already known, all service listeners will be notified of the new service type. 359 * <p> 360 * Service types are automatically registered as they are discovered. 361 * </p> 362 * 363 * @param type 364 * full qualified service type, such as <code>_http._tcp.local.</code>. 365 * @return <code>true</code> if the type or subtype was added, <code>false</code> if the type was already registered. 366 */ registerServiceType(String type)367 public abstract boolean registerServiceType(String type); 368 369 /** 370 * List Services and serviceTypes. Debugging Only 371 * 372 * @deprecated since 3.2.2 373 */ 374 @Deprecated printServices()375 public abstract void printServices(); 376 377 /** 378 * Returns a list of service infos of the specified type. 379 * 380 * @param type 381 * Service type name, such as <code>_http._tcp.local.</code>. 382 * @return An array of service instance. 383 */ list(String type)384 public abstract ServiceInfo[] list(String type); 385 386 /** 387 * Returns a list of service infos of the specified type. 388 * 389 * @param type 390 * Service type name, such as <code>_http._tcp.local.</code>. 391 * @param timeout 392 * timeout in milliseconds. Typical timeout should be 6s. 393 * @return An array of service instance. 394 */ list(String type, long timeout)395 public abstract ServiceInfo[] list(String type, long timeout); 396 397 /** 398 * Returns a list of service infos of the specified type sorted by subtype. Any service that do not register a subtype is listed in the empty subtype section. 399 * 400 * @param type 401 * Service type name, such as <code>_http._tcp.local.</code>. 402 * @return A dictionary of service info by subtypes. 403 */ listBySubtype(String type)404 public abstract Map<String, ServiceInfo[]> listBySubtype(String type); 405 406 /** 407 * Returns a list of service infos of the specified type sorted by subtype. Any service that do not register a subtype is listed in the empty subtype section. 408 * 409 * @param type 410 * Service type name, such as <code>_http._tcp.local.</code>. 411 * @param timeout 412 * timeout in milliseconds. Typical timeout should be 6s. 413 * @return A dictionary of service info by subtypes. 414 */ listBySubtype(String type, long timeout)415 public abstract Map<String, ServiceInfo[]> listBySubtype(String type, long timeout); 416 417 /** 418 * Returns the instance delegate 419 * 420 * @return instance delegate 421 */ getDelegate()422 public abstract Delegate getDelegate(); 423 424 /** 425 * Sets the instance delegate 426 * 427 * @param value 428 * new instance delegate 429 * @return previous instance delegate 430 */ setDelegate(Delegate value)431 public abstract Delegate setDelegate(Delegate value); 432 433 } 434