00001
00002
00003
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
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
00098 addr = loopbackAddress();
00099 aName = ((jmdnsName != null) && (jmdnsName.length() > 0) ? jmdnsName : "computer");
00100 }
00101
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
00184
00185
00186
00187 result = true;
00188 }
00189 if (from.isLoopbackAddress() && (!this.getInetAddress().isLoopbackAddress())) {
00190
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
00426 return true;
00427 }
00428 return _state.waitForCanceled(timeout);
00429 }
00430
00431 }