1
2
3
4
5 package javax.jmdns.impl;
6
7 import java.io.IOException;
8 import java.net.DatagramPacket;
9 import java.net.Inet4Address;
10 import java.net.Inet6Address;
11 import java.net.InetAddress;
12 import java.net.NetworkInterface;
13 import java.net.UnknownHostException;
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.List;
17 import java.util.logging.Level;
18 import java.util.logging.Logger;
19
20 import javax.jmdns.NetworkTopologyDiscovery;
21 import javax.jmdns.impl.constants.DNSConstants;
22 import javax.jmdns.impl.constants.DNSRecordClass;
23 import javax.jmdns.impl.constants.DNSRecordType;
24 import javax.jmdns.impl.constants.DNSState;
25 import javax.jmdns.impl.tasks.DNSTask;
26
27
28
29
30
31
32 public class HostInfo implements DNSStatefulObject {
33 private static Logger logger = Logger.getLogger(HostInfo.class.getName());
34
35 protected String _name;
36
37 protected InetAddress _address;
38
39 protected NetworkInterface _interfaze;
40
41 private final HostInfoState _state;
42
43 private final static class HostInfoState extends DNSStatefulObject.DefaultImplementation {
44
45 private static final long serialVersionUID = -8191476803620402088L;
46
47
48
49
50 public HostInfoState(JmDNSImpl dns) {
51 super();
52 this.setDns(dns);
53 }
54
55 }
56
57
58
59
60
61
62
63
64
65
66 public static HostInfo newHostInfo(InetAddress address, JmDNSImpl dns, String jmdnsName) {
67 HostInfo localhost = null;
68 String aName = "";
69 InetAddress addr = address;
70 try {
71 if (addr == null) {
72 String ip = System.getProperty("net.mdns.interface");
73 if (ip != null) {
74 addr = InetAddress.getByName(ip);
75 } else {
76 addr = InetAddress.getLocalHost();
77 if (addr.isLoopbackAddress()) {
78
79 InetAddress[] addresses = NetworkTopologyDiscovery.Factory.getInstance().getInetAddresses();
80 if (addresses.length > 0) {
81 addr = addresses[0];
82 }
83 }
84 }
85 aName = addr.getHostName();
86 if (addr.isLoopbackAddress()) {
87 logger.warning("Could not find any address beside the loopback.");
88 }
89 } else {
90 aName = addr.getHostName();
91 }
92 if (aName.contains("in-addr.arpa") || (aName.equals(addr.getHostAddress()))) {
93 aName = ((jmdnsName != null) && (jmdnsName.length() > 0) ? jmdnsName : addr.getHostAddress());
94 }
95 } catch (final IOException e) {
96 logger.log(Level.WARNING, "Could not intialize the host network interface on " + address + "because of an error: " + e.getMessage(), e);
97
98 addr = loopbackAddress();
99 aName = ((jmdnsName != null) && (jmdnsName.length() > 0) ? jmdnsName : "computer");
100 }
101
102 aName = aName.replace('.', '-');
103 aName += ".local.";
104 localhost = new HostInfo(addr, aName, dns);
105 return localhost;
106 }
107
108 private static InetAddress loopbackAddress() {
109 try {
110 return InetAddress.getByName(null);
111 } catch (UnknownHostException exception) {
112 return null;
113 }
114 }
115
116
117
118
119 private int hostNameCount;
120
121 private HostInfo(final InetAddress address, final String name, final JmDNSImpl dns) {
122 super();
123 this._state = new HostInfoState(dns);
124 this._address = address;
125 this._name = name;
126 if (address != null) {
127 try {
128 _interfaze = NetworkInterface.getByInetAddress(address);
129 } catch (Exception exception) {
130 logger.log(Level.SEVERE, "LocalHostInfo() exception ", exception);
131 }
132 }
133 }
134
135 public String getName() {
136 return _name;
137 }
138
139 public InetAddress getInetAddress() {
140 return _address;
141 }
142
143 Inet4Address getInet4Address() {
144 if (this.getInetAddress() instanceof Inet4Address) {
145 return (Inet4Address) _address;
146 }
147 return null;
148 }
149
150 Inet6Address getInet6Address() {
151 if (this.getInetAddress() instanceof Inet6Address) {
152 return (Inet6Address) _address;
153 }
154 return null;
155 }
156
157 public NetworkInterface getInterface() {
158 return _interfaze;
159 }
160
161 public boolean conflictWithRecord(DNSRecord.Address record) {
162 DNSRecord.Address hostAddress = this.getDNSAddressRecord(record.getRecordType(), record.isUnique(), DNSConstants.DNS_TTL);
163 if (hostAddress != null) {
164 return hostAddress.sameType(record) && hostAddress.sameName(record) && (!hostAddress.sameValue(record));
165 }
166 return false;
167 }
168
169 synchronized String incrementHostName() {
170 hostNameCount++;
171 int plocal = _name.indexOf(".local.");
172 int punder = _name.lastIndexOf('-');
173 _name = _name.substring(0, (punder == -1 ? plocal : punder)) + "-" + hostNameCount + ".local.";
174 return _name;
175 }
176
177 boolean shouldIgnorePacket(DatagramPacket packet) {
178 boolean result = false;
179 if (this.getInetAddress() != null) {
180 InetAddress from = packet.getAddress();
181 if (from != null) {
182 if (from.isLinkLocalAddress() && (!this.getInetAddress().isLinkLocalAddress())) {
183
184
185
186
187 result = true;
188 }
189 if (from.isLoopbackAddress() && (!this.getInetAddress().isLoopbackAddress())) {
190
191 result = true;
192 }
193 }
194 }
195 return result;
196 }
197
198 DNSRecord.Address getDNSAddressRecord(DNSRecordType type, boolean unique, int ttl) {
199 switch (type) {
200 case TYPE_A:
201 return this.getDNS4AddressRecord(unique, ttl);
202 case TYPE_A6:
203 case TYPE_AAAA:
204 return this.getDNS6AddressRecord(unique, ttl);
205 default:
206 }
207 return null;
208 }
209
210 private DNSRecord.Address getDNS4AddressRecord(boolean unique, int ttl) {
211 if ((this.getInetAddress() instanceof Inet4Address) || ((this.getInetAddress() instanceof Inet6Address) && (((Inet6Address) this.getInetAddress()).isIPv4CompatibleAddress()))) {
212 return new DNSRecord.IPv4Address(this.getName(), DNSRecordClass.CLASS_IN, unique, ttl, this.getInetAddress());
213 }
214 return null;
215 }
216
217 private DNSRecord.Address getDNS6AddressRecord(boolean unique, int ttl) {
218 if (this.getInetAddress() instanceof Inet6Address) {
219 return new DNSRecord.IPv6Address(this.getName(), DNSRecordClass.CLASS_IN, unique, ttl, this.getInetAddress());
220 }
221 return null;
222 }
223
224 DNSRecord.Pointer getDNSReverseAddressRecord(DNSRecordType type, boolean unique, int ttl) {
225 switch (type) {
226 case TYPE_A:
227 return this.getDNS4ReverseAddressRecord(unique, ttl);
228 case TYPE_A6:
229 case TYPE_AAAA:
230 return this.getDNS6ReverseAddressRecord(unique, ttl);
231 default:
232 }
233 return null;
234 }
235
236 private DNSRecord.Pointer getDNS4ReverseAddressRecord(boolean unique, int ttl) {
237 if (this.getInetAddress() instanceof Inet4Address) {
238 return new DNSRecord.Pointer(this.getInetAddress().getHostAddress() + ".in-addr.arpa.", DNSRecordClass.CLASS_IN, unique, ttl, this.getName());
239 }
240 if ((this.getInetAddress() instanceof Inet6Address) && (((Inet6Address) this.getInetAddress()).isIPv4CompatibleAddress())) {
241 byte[] rawAddress = this.getInetAddress().getAddress();
242 String address = (rawAddress[12] & 0xff) + "." + (rawAddress[13] & 0xff) + "." + (rawAddress[14] & 0xff) + "." + (rawAddress[15] & 0xff);
243 return new DNSRecord.Pointer(address + ".in-addr.arpa.", DNSRecordClass.CLASS_IN, unique, ttl, this.getName());
244 }
245 return null;
246 }
247
248 private DNSRecord.Pointer getDNS6ReverseAddressRecord(boolean unique, int ttl) {
249 if (this.getInetAddress() instanceof Inet6Address) {
250 return new DNSRecord.Pointer(this.getInetAddress().getHostAddress() + ".ip6.arpa.", DNSRecordClass.CLASS_IN, unique, ttl, this.getName());
251 }
252 return null;
253 }
254
255 @Override
256 public String toString() {
257 StringBuilder buf = new StringBuilder(1024);
258 buf.append("local host info[");
259 buf.append(getName() != null ? getName() : "no name");
260 buf.append(", ");
261 buf.append(getInterface() != null ? getInterface().getDisplayName() : "???");
262 buf.append(":");
263 buf.append(getInetAddress() != null ? getInetAddress().getHostAddress() : "no address");
264 buf.append(", ");
265 buf.append(_state);
266 buf.append("]");
267 return buf.toString();
268 }
269
270 public Collection<DNSRecord> answers(boolean unique, int ttl) {
271 List<DNSRecord> list = new ArrayList<DNSRecord>();
272 DNSRecord answer = this.getDNS4AddressRecord(unique, ttl);
273 if (answer != null) {
274 list.add(answer);
275 }
276 answer = this.getDNS6AddressRecord(unique, ttl);
277 if (answer != null) {
278 list.add(answer);
279 }
280 return list;
281 }
282
283
284
285
286 @Override
287 public JmDNSImpl getDns() {
288 return this._state.getDns();
289 }
290
291
292
293
294 @Override
295 public boolean advanceState(DNSTask task) {
296 return this._state.advanceState(task);
297 }
298
299
300
301
302 @Override
303 public void removeAssociationWithTask(DNSTask task) {
304 this._state.removeAssociationWithTask(task);
305 }
306
307
308
309
310 @Override
311 public boolean revertState() {
312 return this._state.revertState();
313 }
314
315
316
317
318 @Override
319 public void associateWithTask(DNSTask task, DNSState state) {
320 this._state.associateWithTask(task, state);
321 }
322
323
324
325
326 @Override
327 public boolean isAssociatedWithTask(DNSTask task, DNSState state) {
328 return this._state.isAssociatedWithTask(task, state);
329 }
330
331
332
333
334 @Override
335 public boolean cancelState() {
336 return this._state.cancelState();
337 }
338
339
340
341
342 @Override
343 public boolean closeState() {
344 return this._state.closeState();
345 }
346
347
348
349
350 @Override
351 public boolean recoverState() {
352 return this._state.recoverState();
353 }
354
355
356
357
358 @Override
359 public boolean isProbing() {
360 return this._state.isProbing();
361 }
362
363
364
365
366 @Override
367 public boolean isAnnouncing() {
368 return this._state.isAnnouncing();
369 }
370
371
372
373
374 @Override
375 public boolean isAnnounced() {
376 return this._state.isAnnounced();
377 }
378
379
380
381
382 @Override
383 public boolean isCanceling() {
384 return this._state.isCanceling();
385 }
386
387
388
389
390 @Override
391 public boolean isCanceled() {
392 return this._state.isCanceled();
393 }
394
395
396
397
398 @Override
399 public boolean isClosing() {
400 return this._state.isClosing();
401 }
402
403
404
405
406 @Override
407 public boolean isClosed() {
408 return this._state.isClosed();
409 }
410
411
412
413
414 @Override
415 public boolean waitForAnnounced(long timeout) {
416 return _state.waitForAnnounced(timeout);
417 }
418
419
420
421
422 @Override
423 public boolean waitForCanceled(long timeout) {
424 if (_address == null) {
425
426 return true;
427 }
428 return _state.waitForCanceled(timeout);
429 }
430
431 }