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 */
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.1";
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 getInterface() throws IOException;
162
163 /**
164 * Get service information. If the information is not cached, the method will block until updated information is received.
165 * <p/>
166 * Usage note: Do not call this method from the AWT event dispatcher thread. You will make the user interface unresponsive.
167 *
168 * @param type
169 * fully qualified service type, such as <code>_http._tcp.local.</code> .
170 * @param name
171 * unqualified service name, such as <code>foobar</code> .
172 * @return null if the service information cannot be obtained
173 */
174 public abstract ServiceInfo getServiceInfo(String type, String name);
175
176 /**
177 * Get service information. If the information is not cached, the method will block for the given timeout until updated information is received.
178 * <p/>
179 * 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.
180 *
181 * @param type
182 * full qualified service type, such as <code>_http._tcp.local.</code> .
183 * @param name
184 * unqualified service name, such as <code>foobar</code> .
185 * @param timeout
186 * timeout in milliseconds. Typical timeout should be 5s.
187 * @return null if the service information cannot be obtained
188 */
189 public abstract ServiceInfo getServiceInfo(String type, String name, long timeout);
190
191 /**
192 * Get service information. If the information is not cached, the method will block until updated information is received.
193 * <p/>
194 * Usage note: Do not call this method from the AWT event dispatcher thread. You will make the user interface unresponsive.
195 *
196 * @param type
197 * fully qualified service type, such as <code>_http._tcp.local.</code> .
198 * @param name
199 * unqualified service name, such as <code>foobar</code> .
200 * @param persistent
201 * if <code>true</code> ServiceListener.resolveService will be called whenever new new information is received.
202 * @return null if the service information cannot be obtained
203 */
204 public abstract ServiceInfo getServiceInfo(String type, String name, boolean persistent);
205
206 /**
207 * Get service information. If the information is not cached, the method will block for the given timeout until updated information is received.
208 * <p/>
209 * 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.
210 *
211 * @param type
212 * full qualified service type, such as <code>_http._tcp.local.</code> .
213 * @param name
214 * unqualified service name, such as <code>foobar</code> .
215 * @param timeout
216 * timeout in milliseconds. Typical timeout should be 5s.
217 * @param persistent
218 * if <code>true</code> ServiceListener.resolveService will be called whenever new new information is received.
219 * @return null if the service information cannot be obtained
220 */
221 public abstract ServiceInfo getServiceInfo(String type, String name, boolean persistent, long timeout);
222
223 /**
224 * Request service information. The information about the service is requested and the ServiceListener.resolveService method is called as soon as it is available.
225 * <p/>
226 * Usage note: Do not call this method from the AWT event dispatcher thread. You will make the user interface unresponsive.
227 *
228 * @param type
229 * full qualified service type, such as <code>_http._tcp.local.</code> .
230 * @param name
231 * unqualified service name, such as <code>foobar</code> .
232 */
233 public abstract void requestServiceInfo(String type, String name);
234
235 /**
236 * Request service information. The information about the service is requested and the ServiceListener.resolveService method is called as soon as it is available.
237 * <p/>
238 * Usage note: Do not call this method from the AWT event dispatcher thread. You will make the user interface unresponsive.
239 *
240 * @param type
241 * full qualified service type, such as <code>_http._tcp.local.</code> .
242 * @param name
243 * unqualified service name, such as <code>foobar</code> .
244 * @param persistent
245 * if <code>true</code> ServiceListener.resolveService will be called whenever new new information is received.
246 */
247 public abstract void requestServiceInfo(String type, String name, boolean persistent);
248
249 /**
250 * Request service information. The information about the service is requested and the ServiceListener.resolveService method is called as soon as it is available.
251 *
252 * @param type
253 * full qualified service type, such as <code>_http._tcp.local.</code> .
254 * @param name
255 * unqualified service name, such as <code>foobar</code> .
256 * @param timeout
257 * timeout in milliseconds
258 */
259 public abstract void requestServiceInfo(String type, String name, long timeout);
260
261 /**
262 * Request service information. The information about the service is requested and the ServiceListener.resolveService method is called as soon as it is available.
263 *
264 * @param type
265 * full qualified service type, such as <code>_http._tcp.local.</code> .
266 * @param name
267 * unqualified service name, such as <code>foobar</code> .
268 * @param persistent
269 * if <code>true</code> ServiceListener.resolveService will be called whenever new new information is received.
270 * @param timeout
271 * timeout in milliseconds
272 */
273 public abstract void requestServiceInfo(String type, String name, boolean persistent, long timeout);
274
275 /**
276 * Listen for service types.
277 *
278 * @param listener
279 * listener for service types
280 * @exception IOException
281 * if there is an error in the underlying protocol, such as a TCP error.
282 */
283 public abstract void addServiceTypeListener(ServiceTypeListener listener) throws IOException;
284
285 /**
286 * Remove listener for service types.
287 *
288 * @param listener
289 * listener for service types
290 */
291 public abstract void removeServiceTypeListener(ServiceTypeListener listener);
292
293 /**
294 * Listen for services of a given type. The type has to be a fully qualified type name such as <code>_http._tcp.local.</code>.
295 *
296 * @param type
297 * full qualified service type, such as <code>_http._tcp.local.</code>.
298 * @param listener
299 * listener for service updates
300 */
301 public abstract void addServiceListener(String type, ServiceListener listener);
302
303 /**
304 * Remove listener for services of a given type.
305 *
306 * @param type
307 * full qualified service type, such as <code>_http._tcp.local.</code>.
308 * @param listener
309 * listener for service updates
310 */
311 public abstract void removeServiceListener(String type, ServiceListener listener);
312
313 /**
314 * 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>
315 * Note that the given {@code ServiceInfo} is bound to this {@code JmDNS} instance, and should not be reused for any other {@linkplain #registerService(ServiceInfo)}.
316 *
317 * @param info
318 * service info to register
319 * @exception IOException
320 * if there is an error in the underlying protocol, such as a TCP error.
321 */
322 public abstract void registerService(ServiceInfo info) throws IOException;
323
324 /**
325 * Unregister a service. The service should have been registered.
326 * <p>
327 * <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/>
328 * This is support for shared records that can be rescued by some other cooperation DNS.
329 *
330 * <pre>
331 * 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.
332 * </pre>
333 *
334 * </p>
335 *
336 * @param info
337 * service info to remove
338 */
339 public abstract void unregisterService(ServiceInfo info);
340
341 /**
342 * Unregister all services.
343 */
344 public abstract void unregisterAllServices();
345
346 /**
347 * Register a service type. If this service type was not already known, all service listeners will be notified of the new service type.
348 * <p>
349 * Service types are automatically registered as they are discovered.
350 * </p>
351 *
352 * @param type
353 * full qualified service type, such as <code>_http._tcp.local.</code>.
354 * @return <code>true</code> if the type or subtype was added, <code>false</code> if the type was already registered.
355 */
356 public abstract boolean registerServiceType(String type);
357
358 /**
359 * List Services and serviceTypes. Debugging Only
360 *
361 * @deprecated since 3.2.2
362 */
363 @Deprecated
364 public abstract void printServices();
365
366 /**
367 * Returns a list of service infos of the specified type.
368 *
369 * @param type
370 * Service type name, such as <code>_http._tcp.local.</code>.
371 * @return An array of service instance.
372 */
373 public abstract ServiceInfo[] list(String type);
374
375 /**
376 * Returns a list of service infos of the specified type.
377 *
378 * @param type
379 * Service type name, such as <code>_http._tcp.local.</code>.
380 * @param timeout
381 * timeout in milliseconds. Typical timeout should be 6s.
382 * @return An array of service instance.
383 */
384 public abstract ServiceInfo[] list(String type, long timeout);
385
386 /**
387 * 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.
388 *
389 * @param type
390 * Service type name, such as <code>_http._tcp.local.</code>.
391 * @return A dictionary of service info by subtypes.
392 */
393 public abstract Map<String, ServiceInfo[]> listBySubtype(String type);
394
395 /**
396 * 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.
397 *
398 * @param type
399 * Service type name, such as <code>_http._tcp.local.</code>.
400 * @param timeout
401 * timeout in milliseconds. Typical timeout should be 6s.
402 * @return A dictionary of service info by subtypes.
403 */
404 public abstract Map<String, ServiceInfo[]> listBySubtype(String type, long timeout);
405
406 /**
407 * Returns the instance delegate
408 *
409 * @return instance delegate
410 */
411 public abstract Delegate getDelegate();
412
413 /**
414 * Sets the instance delegate
415 *
416 * @param value
417 * new instance delegate
418 * @return previous instance delegate
419 */
420 public abstract Delegate setDelegate(Delegate value);
421
422 }