summaryrefslogtreecommitdiff
path: root/src/javax/jmdns/impl/HostInfo.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/javax/jmdns/impl/HostInfo.java')
-rwxr-xr-xsrc/javax/jmdns/impl/HostInfo.java431
1 files changed, 431 insertions, 0 deletions
diff --git a/src/javax/jmdns/impl/HostInfo.java b/src/javax/jmdns/impl/HostInfo.java
new file mode 100755
index 0000000..1f9650e
--- /dev/null
+++ b/src/javax/jmdns/impl/HostInfo.java
@@ -0,0 +1,431 @@
+// Copyright 2003-2005 Arthur van Hoff, Rick Blair
+// Licensed under Apache License version 2.0
+// Original license LGPL
+
+package javax.jmdns.impl;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.jmdns.NetworkTopologyDiscovery;
+import javax.jmdns.impl.constants.DNSConstants;
+import javax.jmdns.impl.constants.DNSRecordClass;
+import javax.jmdns.impl.constants.DNSRecordType;
+import javax.jmdns.impl.constants.DNSState;
+import javax.jmdns.impl.tasks.DNSTask;
+
+/**
+ * HostInfo information on the local host to be able to cope with change of addresses.
+ *
+ * @author Pierre Frisch, Werner Randelshofer
+ */
+public class HostInfo implements DNSStatefulObject {
+ private static Logger logger = Logger.getLogger(HostInfo.class.getName());
+
+ protected String _name;
+
+ protected InetAddress _address;
+
+ protected NetworkInterface _interfaze;
+
+ private final HostInfoState _state;
+
+ private final static class HostInfoState extends DNSStatefulObject.DefaultImplementation {
+
+ private static final long serialVersionUID = -8191476803620402088L;
+
+ /**
+ * @param dns
+ */
+ public HostInfoState(JmDNSImpl dns) {
+ super();
+ this.setDns(dns);
+ }
+
+ }
+
+ /**
+ * @param address
+ * IP address to bind
+ * @param dns
+ * JmDNS instance
+ * @param jmdnsName
+ * JmDNS name
+ * @return new HostInfo
+ */
+ public static HostInfo newHostInfo(InetAddress address, JmDNSImpl dns, String jmdnsName) {
+ HostInfo localhost = null;
+ String aName = "";
+ InetAddress addr = address;
+ try {
+ if (addr == null) {
+ String ip = System.getProperty("net.mdns.interface");
+ if (ip != null) {
+ addr = InetAddress.getByName(ip);
+ } else {
+ addr = InetAddress.getLocalHost();
+ if (addr.isLoopbackAddress()) {
+ // Find local address that isn't a loopback address
+ InetAddress[] addresses = NetworkTopologyDiscovery.Factory.getInstance().getInetAddresses();
+ if (addresses.length > 0) {
+ addr = addresses[0];
+ }
+ }
+ }
+ aName = addr.getHostName();
+ if (addr.isLoopbackAddress()) {
+ logger.warning("Could not find any address beside the loopback.");
+ }
+ } else {
+ aName = addr.getHostName();
+ }
+ if (aName.contains("in-addr.arpa") || (aName.equals(addr.getHostAddress()))) {
+ aName = ((jmdnsName != null) && (jmdnsName.length() > 0) ? jmdnsName : addr.getHostAddress());
+ }
+ } catch (final IOException e) {
+ logger.log(Level.WARNING, "Could not intialize the host network interface on " + address + "because of an error: " + e.getMessage(), e);
+ // This is only used for running unit test on Debian / Ubuntu
+ addr = loopbackAddress();
+ aName = ((jmdnsName != null) && (jmdnsName.length() > 0) ? jmdnsName : "computer");
+ }
+ // A host name with "." is illegal. so strip off everything and append .local.
+ aName = aName.replace('.', '-');
+ aName += ".local.";
+ localhost = new HostInfo(addr, aName, dns);
+ return localhost;
+ }
+
+ private static InetAddress loopbackAddress() {
+ try {
+ return InetAddress.getByName(null);
+ } catch (UnknownHostException exception) {
+ return null;
+ }
+ }
+
+ /**
+ * This is used to create a unique name for the host name.
+ */
+ private int hostNameCount;
+
+ private HostInfo(final InetAddress address, final String name, final JmDNSImpl dns) {
+ super();
+ this._state = new HostInfoState(dns);
+ this._address = address;
+ this._name = name;
+ if (address != null) {
+ try {
+ _interfaze = NetworkInterface.getByInetAddress(address);
+ } catch (Exception exception) {
+ logger.log(Level.SEVERE, "LocalHostInfo() exception ", exception);
+ }
+ }
+ }
+
+ public String getName() {
+ return _name;
+ }
+
+ public InetAddress getInetAddress() {
+ return _address;
+ }
+
+ Inet4Address getInet4Address() {
+ if (this.getInetAddress() instanceof Inet4Address) {
+ return (Inet4Address) _address;
+ }
+ return null;
+ }
+
+ Inet6Address getInet6Address() {
+ if (this.getInetAddress() instanceof Inet6Address) {
+ return (Inet6Address) _address;
+ }
+ return null;
+ }
+
+ public NetworkInterface getInterface() {
+ return _interfaze;
+ }
+
+ public boolean conflictWithRecord(DNSRecord.Address record) {
+ DNSRecord.Address hostAddress = this.getDNSAddressRecord(record.getRecordType(), record.isUnique(), DNSConstants.DNS_TTL);
+ if (hostAddress != null) {
+ return hostAddress.sameType(record) && hostAddress.sameName(record) && (!hostAddress.sameValue(record));
+ }
+ return false;
+ }
+
+ synchronized String incrementHostName() {
+ hostNameCount++;
+ int plocal = _name.indexOf(".local.");
+ int punder = _name.lastIndexOf('-');
+ _name = _name.substring(0, (punder == -1 ? plocal : punder)) + "-" + hostNameCount + ".local.";
+ return _name;
+ }
+
+ boolean shouldIgnorePacket(DatagramPacket packet) {
+ boolean result = false;
+ if (this.getInetAddress() != null) {
+ InetAddress from = packet.getAddress();
+ if (from != null) {
+ if (from.isLinkLocalAddress() && (!this.getInetAddress().isLinkLocalAddress())) {
+ // Ignore linklocal packets on regular interfaces, unless this is
+ // also a linklocal interface. This is to avoid duplicates. This is
+ // a terrible hack caused by the lack of an API to get the address
+ // of the interface on which the packet was received.
+ result = true;
+ }
+ if (from.isLoopbackAddress() && (!this.getInetAddress().isLoopbackAddress())) {
+ // Ignore loopback packets on a regular interface unless this is also a loopback interface.
+ result = true;
+ }
+ }
+ }
+ return result;
+ }
+
+ DNSRecord.Address getDNSAddressRecord(DNSRecordType type, boolean unique, int ttl) {
+ switch (type) {
+ case TYPE_A:
+ return this.getDNS4AddressRecord(unique, ttl);
+ case TYPE_A6:
+ case TYPE_AAAA:
+ return this.getDNS6AddressRecord(unique, ttl);
+ default:
+ }
+ return null;
+ }
+
+ private DNSRecord.Address getDNS4AddressRecord(boolean unique, int ttl) {
+ if ((this.getInetAddress() instanceof Inet4Address) || ((this.getInetAddress() instanceof Inet6Address) && (((Inet6Address) this.getInetAddress()).isIPv4CompatibleAddress()))) {
+ return new DNSRecord.IPv4Address(this.getName(), DNSRecordClass.CLASS_IN, unique, ttl, this.getInetAddress());
+ }
+ return null;
+ }
+
+ private DNSRecord.Address getDNS6AddressRecord(boolean unique, int ttl) {
+ if (this.getInetAddress() instanceof Inet6Address) {
+ return new DNSRecord.IPv6Address(this.getName(), DNSRecordClass.CLASS_IN, unique, ttl, this.getInetAddress());
+ }
+ return null;
+ }
+
+ DNSRecord.Pointer getDNSReverseAddressRecord(DNSRecordType type, boolean unique, int ttl) {
+ switch (type) {
+ case TYPE_A:
+ return this.getDNS4ReverseAddressRecord(unique, ttl);
+ case TYPE_A6:
+ case TYPE_AAAA:
+ return this.getDNS6ReverseAddressRecord(unique, ttl);
+ default:
+ }
+ return null;
+ }
+
+ private DNSRecord.Pointer getDNS4ReverseAddressRecord(boolean unique, int ttl) {
+ if (this.getInetAddress() instanceof Inet4Address) {
+ return new DNSRecord.Pointer(this.getInetAddress().getHostAddress() + ".in-addr.arpa.", DNSRecordClass.CLASS_IN, unique, ttl, this.getName());
+ }
+ if ((this.getInetAddress() instanceof Inet6Address) && (((Inet6Address) this.getInetAddress()).isIPv4CompatibleAddress())) {
+ byte[] rawAddress = this.getInetAddress().getAddress();
+ String address = (rawAddress[12] & 0xff) + "." + (rawAddress[13] & 0xff) + "." + (rawAddress[14] & 0xff) + "." + (rawAddress[15] & 0xff);
+ return new DNSRecord.Pointer(address + ".in-addr.arpa.", DNSRecordClass.CLASS_IN, unique, ttl, this.getName());
+ }
+ return null;
+ }
+
+ private DNSRecord.Pointer getDNS6ReverseAddressRecord(boolean unique, int ttl) {
+ if (this.getInetAddress() instanceof Inet6Address) {
+ return new DNSRecord.Pointer(this.getInetAddress().getHostAddress() + ".ip6.arpa.", DNSRecordClass.CLASS_IN, unique, ttl, this.getName());
+ }
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder buf = new StringBuilder(1024);
+ buf.append("local host info[");
+ buf.append(getName() != null ? getName() : "no name");
+ buf.append(", ");
+ buf.append(getInterface() != null ? getInterface().getDisplayName() : "???");
+ buf.append(":");
+ buf.append(getInetAddress() != null ? getInetAddress().getHostAddress() : "no address");
+ buf.append(", ");
+ buf.append(_state);
+ buf.append("]");
+ return buf.toString();
+ }
+
+ public Collection<DNSRecord> answers(boolean unique, int ttl) {
+ List<DNSRecord> list = new ArrayList<DNSRecord>();
+ DNSRecord answer = this.getDNS4AddressRecord(unique, ttl);
+ if (answer != null) {
+ list.add(answer);
+ }
+ answer = this.getDNS6AddressRecord(unique, ttl);
+ if (answer != null) {
+ list.add(answer);
+ }
+ return list;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public JmDNSImpl getDns() {
+ return this._state.getDns();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean advanceState(DNSTask task) {
+ return this._state.advanceState(task);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void removeAssociationWithTask(DNSTask task) {
+ this._state.removeAssociationWithTask(task);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean revertState() {
+ return this._state.revertState();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void associateWithTask(DNSTask task, DNSState state) {
+ this._state.associateWithTask(task, state);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isAssociatedWithTask(DNSTask task, DNSState state) {
+ return this._state.isAssociatedWithTask(task, state);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean cancelState() {
+ return this._state.cancelState();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean closeState() {
+ return this._state.closeState();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean recoverState() {
+ return this._state.recoverState();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isProbing() {
+ return this._state.isProbing();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isAnnouncing() {
+ return this._state.isAnnouncing();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isAnnounced() {
+ return this._state.isAnnounced();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isCanceling() {
+ return this._state.isCanceling();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isCanceled() {
+ return this._state.isCanceled();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isClosing() {
+ return this._state.isClosing();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isClosed() {
+ return this._state.isClosed();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean waitForAnnounced(long timeout) {
+ return _state.waitForAnnounced(timeout);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean waitForCanceled(long timeout) {
+ if (_address == null) {
+ // No need to wait this was never announced.
+ return true;
+ }
+ return _state.waitForCanceled(timeout);
+ }
+
+}