$search
00001 // Copyright 2003-2005 Arthur van Hoff, Rick Blair 00002 // Licensed under Apache License version 2.0 00003 // Original license LGPL 00004 00005 package javax.jmdns.impl; 00006 00007 import java.io.IOException; 00008 import java.net.DatagramPacket; 00009 import java.net.Inet4Address; 00010 import java.net.Inet6Address; 00011 import java.net.InetAddress; 00012 import java.net.NetworkInterface; 00013 import java.net.UnknownHostException; 00014 import java.util.ArrayList; 00015 import java.util.Collection; 00016 import java.util.List; 00017 import java.util.logging.Level; 00018 import java.util.logging.Logger; 00019 00020 import javax.jmdns.NetworkTopologyDiscovery; 00021 import javax.jmdns.impl.constants.DNSConstants; 00022 import javax.jmdns.impl.constants.DNSRecordClass; 00023 import javax.jmdns.impl.constants.DNSRecordType; 00024 import javax.jmdns.impl.constants.DNSState; 00025 import javax.jmdns.impl.tasks.DNSTask; 00026 00032 public class HostInfo implements DNSStatefulObject { 00033 private static Logger logger = Logger.getLogger(HostInfo.class.getName()); 00034 00035 protected String _name; 00036 00037 protected InetAddress _address; 00038 00039 protected NetworkInterface _interfaze; 00040 00041 private final HostInfoState _state; 00042 00043 private final static class HostInfoState extends DNSStatefulObject.DefaultImplementation { 00044 00045 private static final long serialVersionUID = -8191476803620402088L; 00046 00050 public HostInfoState(JmDNSImpl dns) { 00051 super(); 00052 this.setDns(dns); 00053 } 00054 00055 } 00056 00066 public static HostInfo newHostInfo(InetAddress address, JmDNSImpl dns, String jmdnsName) { 00067 HostInfo localhost = null; 00068 String aName = ""; 00069 InetAddress addr = address; 00070 try { 00071 if (addr == null) { 00072 String ip = System.getProperty("net.mdns.interface"); 00073 if (ip != null) { 00074 addr = InetAddress.getByName(ip); 00075 } else { 00076 addr = InetAddress.getLocalHost(); 00077 if (addr.isLoopbackAddress()) { 00078 // Find local address that isn't a loopback address 00079 InetAddress[] addresses = NetworkTopologyDiscovery.Factory.getInstance().getInetAddresses(); 00080 if (addresses.length > 0) { 00081 addr = addresses[0]; 00082 } 00083 } 00084 } 00085 aName = addr.getHostName(); 00086 if (addr.isLoopbackAddress()) { 00087 logger.warning("Could not find any address beside the loopback."); 00088 } 00089 } else { 00090 aName = addr.getHostName(); 00091 } 00092 if (aName.contains("in-addr.arpa") || (aName.equals(addr.getHostAddress()))) { 00093 aName = ((jmdnsName != null) && (jmdnsName.length() > 0) ? jmdnsName : addr.getHostAddress()); 00094 } 00095 } catch (final IOException e) { 00096 logger.log(Level.WARNING, "Could not intialize the host network interface on " + address + "because of an error: " + e.getMessage(), e); 00097 // This is only used for running unit test on Debian / Ubuntu 00098 addr = loopbackAddress(); 00099 aName = ((jmdnsName != null) && (jmdnsName.length() > 0) ? jmdnsName : "computer"); 00100 } 00101 // A host name with "." is illegal. so strip off everything and append .local. 00102 aName = aName.replace('.', '-'); 00103 aName += ".local."; 00104 localhost = new HostInfo(addr, aName, dns); 00105 return localhost; 00106 } 00107 00108 private static InetAddress loopbackAddress() { 00109 try { 00110 return InetAddress.getByName(null); 00111 } catch (UnknownHostException exception) { 00112 return null; 00113 } 00114 } 00115 00119 private int hostNameCount; 00120 00121 private HostInfo(final InetAddress address, final String name, final JmDNSImpl dns) { 00122 super(); 00123 this._state = new HostInfoState(dns); 00124 this._address = address; 00125 this._name = name; 00126 if (address != null) { 00127 try { 00128 _interfaze = NetworkInterface.getByInetAddress(address); 00129 } catch (Exception exception) { 00130 logger.log(Level.SEVERE, "LocalHostInfo() exception ", exception); 00131 } 00132 } 00133 } 00134 00135 public String getName() { 00136 return _name; 00137 } 00138 00139 public InetAddress getInetAddress() { 00140 return _address; 00141 } 00142 00143 Inet4Address getInet4Address() { 00144 if (this.getInetAddress() instanceof Inet4Address) { 00145 return (Inet4Address) _address; 00146 } 00147 return null; 00148 } 00149 00150 Inet6Address getInet6Address() { 00151 if (this.getInetAddress() instanceof Inet6Address) { 00152 return (Inet6Address) _address; 00153 } 00154 return null; 00155 } 00156 00157 public NetworkInterface getInterface() { 00158 return _interfaze; 00159 } 00160 00161 public boolean conflictWithRecord(DNSRecord.Address record) { 00162 DNSRecord.Address hostAddress = this.getDNSAddressRecord(record.getRecordType(), record.isUnique(), DNSConstants.DNS_TTL); 00163 if (hostAddress != null) { 00164 return hostAddress.sameType(record) && hostAddress.sameName(record) && (!hostAddress.sameValue(record)); 00165 } 00166 return false; 00167 } 00168 00169 synchronized String incrementHostName() { 00170 hostNameCount++; 00171 int plocal = _name.indexOf(".local."); 00172 int punder = _name.lastIndexOf('-'); 00173 _name = _name.substring(0, (punder == -1 ? plocal : punder)) + "-" + hostNameCount + ".local."; 00174 return _name; 00175 } 00176 00177 boolean shouldIgnorePacket(DatagramPacket packet) { 00178 boolean result = false; 00179 if (this.getInetAddress() != null) { 00180 InetAddress from = packet.getAddress(); 00181 if (from != null) { 00182 if (from.isLinkLocalAddress() && (!this.getInetAddress().isLinkLocalAddress())) { 00183 // Ignore linklocal packets on regular interfaces, unless this is 00184 // also a linklocal interface. This is to avoid duplicates. This is 00185 // a terrible hack caused by the lack of an API to get the address 00186 // of the interface on which the packet was received. 00187 result = true; 00188 } 00189 if (from.isLoopbackAddress() && (!this.getInetAddress().isLoopbackAddress())) { 00190 // Ignore loopback packets on a regular interface unless this is also a loopback interface. 00191 result = true; 00192 } 00193 } 00194 } 00195 return result; 00196 } 00197 00198 DNSRecord.Address getDNSAddressRecord(DNSRecordType type, boolean unique, int ttl) { 00199 switch (type) { 00200 case TYPE_A: 00201 return this.getDNS4AddressRecord(unique, ttl); 00202 case TYPE_A6: 00203 case TYPE_AAAA: 00204 return this.getDNS6AddressRecord(unique, ttl); 00205 default: 00206 } 00207 return null; 00208 } 00209 00210 private DNSRecord.Address getDNS4AddressRecord(boolean unique, int ttl) { 00211 if ((this.getInetAddress() instanceof Inet4Address) || ((this.getInetAddress() instanceof Inet6Address) && (((Inet6Address) this.getInetAddress()).isIPv4CompatibleAddress()))) { 00212 return new DNSRecord.IPv4Address(this.getName(), DNSRecordClass.CLASS_IN, unique, ttl, this.getInetAddress()); 00213 } 00214 return null; 00215 } 00216 00217 private DNSRecord.Address getDNS6AddressRecord(boolean unique, int ttl) { 00218 if (this.getInetAddress() instanceof Inet6Address) { 00219 return new DNSRecord.IPv6Address(this.getName(), DNSRecordClass.CLASS_IN, unique, ttl, this.getInetAddress()); 00220 } 00221 return null; 00222 } 00223 00224 DNSRecord.Pointer getDNSReverseAddressRecord(DNSRecordType type, boolean unique, int ttl) { 00225 switch (type) { 00226 case TYPE_A: 00227 return this.getDNS4ReverseAddressRecord(unique, ttl); 00228 case TYPE_A6: 00229 case TYPE_AAAA: 00230 return this.getDNS6ReverseAddressRecord(unique, ttl); 00231 default: 00232 } 00233 return null; 00234 } 00235 00236 private DNSRecord.Pointer getDNS4ReverseAddressRecord(boolean unique, int ttl) { 00237 if (this.getInetAddress() instanceof Inet4Address) { 00238 return new DNSRecord.Pointer(this.getInetAddress().getHostAddress() + ".in-addr.arpa.", DNSRecordClass.CLASS_IN, unique, ttl, this.getName()); 00239 } 00240 if ((this.getInetAddress() instanceof Inet6Address) && (((Inet6Address) this.getInetAddress()).isIPv4CompatibleAddress())) { 00241 byte[] rawAddress = this.getInetAddress().getAddress(); 00242 String address = (rawAddress[12] & 0xff) + "." + (rawAddress[13] & 0xff) + "." + (rawAddress[14] & 0xff) + "." + (rawAddress[15] & 0xff); 00243 return new DNSRecord.Pointer(address + ".in-addr.arpa.", DNSRecordClass.CLASS_IN, unique, ttl, this.getName()); 00244 } 00245 return null; 00246 } 00247 00248 private DNSRecord.Pointer getDNS6ReverseAddressRecord(boolean unique, int ttl) { 00249 if (this.getInetAddress() instanceof Inet6Address) { 00250 return new DNSRecord.Pointer(this.getInetAddress().getHostAddress() + ".ip6.arpa.", DNSRecordClass.CLASS_IN, unique, ttl, this.getName()); 00251 } 00252 return null; 00253 } 00254 00255 @Override 00256 public String toString() { 00257 StringBuilder buf = new StringBuilder(1024); 00258 buf.append("local host info["); 00259 buf.append(getName() != null ? getName() : "no name"); 00260 buf.append(", "); 00261 buf.append(getInterface() != null ? getInterface().getDisplayName() : "???"); 00262 buf.append(":"); 00263 buf.append(getInetAddress() != null ? getInetAddress().getHostAddress() : "no address"); 00264 buf.append(", "); 00265 buf.append(_state); 00266 buf.append("]"); 00267 return buf.toString(); 00268 } 00269 00270 public Collection<DNSRecord> answers(boolean unique, int ttl) { 00271 List<DNSRecord> list = new ArrayList<DNSRecord>(); 00272 DNSRecord answer = this.getDNS4AddressRecord(unique, ttl); 00273 if (answer != null) { 00274 list.add(answer); 00275 } 00276 answer = this.getDNS6AddressRecord(unique, ttl); 00277 if (answer != null) { 00278 list.add(answer); 00279 } 00280 return list; 00281 } 00282 00286 @Override 00287 public JmDNSImpl getDns() { 00288 return this._state.getDns(); 00289 } 00290 00294 @Override 00295 public boolean advanceState(DNSTask task) { 00296 return this._state.advanceState(task); 00297 } 00298 00302 @Override 00303 public void removeAssociationWithTask(DNSTask task) { 00304 this._state.removeAssociationWithTask(task); 00305 } 00306 00310 @Override 00311 public boolean revertState() { 00312 return this._state.revertState(); 00313 } 00314 00318 @Override 00319 public void associateWithTask(DNSTask task, DNSState state) { 00320 this._state.associateWithTask(task, state); 00321 } 00322 00326 @Override 00327 public boolean isAssociatedWithTask(DNSTask task, DNSState state) { 00328 return this._state.isAssociatedWithTask(task, state); 00329 } 00330 00334 @Override 00335 public boolean cancelState() { 00336 return this._state.cancelState(); 00337 } 00338 00342 @Override 00343 public boolean closeState() { 00344 return this._state.closeState(); 00345 } 00346 00350 @Override 00351 public boolean recoverState() { 00352 return this._state.recoverState(); 00353 } 00354 00358 @Override 00359 public boolean isProbing() { 00360 return this._state.isProbing(); 00361 } 00362 00366 @Override 00367 public boolean isAnnouncing() { 00368 return this._state.isAnnouncing(); 00369 } 00370 00374 @Override 00375 public boolean isAnnounced() { 00376 return this._state.isAnnounced(); 00377 } 00378 00382 @Override 00383 public boolean isCanceling() { 00384 return this._state.isCanceling(); 00385 } 00386 00390 @Override 00391 public boolean isCanceled() { 00392 return this._state.isCanceled(); 00393 } 00394 00398 @Override 00399 public boolean isClosing() { 00400 return this._state.isClosing(); 00401 } 00402 00406 @Override 00407 public boolean isClosed() { 00408 return this._state.isClosed(); 00409 } 00410 00414 @Override 00415 public boolean waitForAnnounced(long timeout) { 00416 return _state.waitForAnnounced(timeout); 00417 } 00418 00422 @Override 00423 public boolean waitForCanceled(long timeout) { 00424 if (_address == null) { 00425 // No need to wait this was never announced. 00426 return true; 00427 } 00428 return _state.waitForCanceled(timeout); 00429 } 00430 00431 }