1// /Copyright 2003-2005 Arthur van Hoff, Rick Blair
2// Licensed under Apache License version 2.0
3// Original license LGPL
4
5package javax.jmdns;
6
7import java.io.Closeable;
8import java.io.IOException;
9import java.net.InetAddress;
10import java.util.Collection;
11import java.util.Map;
12
13import 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 */
20public 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         */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
350    public abstract void unregisterService(ServiceInfo info);
351
352    /**
353     * Unregister all services.
354     */
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     */
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
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     */
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     */
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     */
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     */
415    public abstract Map<String, ServiceInfo[]> listBySubtype(String type, long timeout);
416
417    /**
418     * Returns the instance delegate
419     *
420     * @return instance delegate
421     */
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     */
431    public abstract Delegate setDelegate(Delegate value);
432
433}
434