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