summaryrefslogtreecommitdiff
path: root/src/javax/jmdns/impl/DNSEntry.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/javax/jmdns/impl/DNSEntry.java')
-rw-r--r--src/javax/jmdns/impl/DNSEntry.java296
1 files changed, 296 insertions, 0 deletions
diff --git a/src/javax/jmdns/impl/DNSEntry.java b/src/javax/jmdns/impl/DNSEntry.java
new file mode 100644
index 0000000..472ec65
--- /dev/null
+++ b/src/javax/jmdns/impl/DNSEntry.java
@@ -0,0 +1,296 @@
+// 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.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Map;
+
+import javax.jmdns.ServiceInfo.Fields;
+import javax.jmdns.impl.constants.DNSRecordClass;
+import javax.jmdns.impl.constants.DNSRecordType;
+
+/**
+ * DNS entry with a name, type, and class. This is the base class for questions and records.
+ *
+ * @author Arthur van Hoff, Pierre Frisch, Rick Blair
+ */
+public abstract class DNSEntry {
+ // private static Logger logger = Logger.getLogger(DNSEntry.class.getName());
+ private final String _key;
+
+ private final String _name;
+
+ private final String _type;
+
+ private final DNSRecordType _recordType;
+
+ private final DNSRecordClass _dnsClass;
+
+ private final boolean _unique;
+
+ final Map<Fields, String> _qualifiedNameMap;
+
+ /**
+ * Create an entry.
+ */
+ DNSEntry(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) {
+ _name = name;
+ // _key = (name != null ? name.trim().toLowerCase() : null);
+ _recordType = type;
+ _dnsClass = recordClass;
+ _unique = unique;
+ _qualifiedNameMap = ServiceInfoImpl.decodeQualifiedNameMapForType(this.getName());
+ String domain = _qualifiedNameMap.get(Fields.Domain);
+ String protocol = _qualifiedNameMap.get(Fields.Protocol);
+ String application = _qualifiedNameMap.get(Fields.Application);
+ String instance = _qualifiedNameMap.get(Fields.Instance).toLowerCase();
+ _type = (application.length() > 0 ? "_" + application + "." : "") + (protocol.length() > 0 ? "_" + protocol + "." : "") + domain + ".";
+ _key = ((instance.length() > 0 ? instance + "." : "") + _type).toLowerCase();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ boolean result = false;
+ if (obj instanceof DNSEntry) {
+ DNSEntry other = (DNSEntry) obj;
+ result = this.getKey().equals(other.getKey()) && this.getRecordType().equals(other.getRecordType()) && this.getRecordClass() == other.getRecordClass();
+ }
+ return result;
+ }
+
+ /**
+ * Check if two entries have exactly the same name, type, and class.
+ *
+ * @param entry
+ * @return <code>true</code> if the two entries have are for the same record, <code>false</code> otherwise
+ */
+ public boolean isSameEntry(DNSEntry entry) {
+ return this.getKey().equals(entry.getKey()) && this.getRecordType().equals(entry.getRecordType()) && ((DNSRecordClass.CLASS_ANY == entry.getRecordClass()) || this.getRecordClass().equals(entry.getRecordClass()));
+ }
+
+ /**
+ * Check if two entries have the same subtype.
+ *
+ * @param other
+ * @return <code>true</code> if the two entries have are for the same subtype, <code>false</code> otherwise
+ */
+ public boolean sameSubtype(DNSEntry other) {
+ return this.getSubtype().equals(other.getSubtype());
+ }
+
+ /**
+ * Returns the subtype of this entry
+ *
+ * @return subtype of this entry
+ */
+ public String getSubtype() {
+ String subtype = this.getQualifiedNameMap().get(Fields.Subtype);
+ return (subtype != null ? subtype : "");
+ }
+
+ /**
+ * Returns the name of this entry
+ *
+ * @return name of this entry
+ */
+ public String getName() {
+ return (_name != null ? _name : "");
+ }
+
+ /**
+ * @return the type
+ */
+ public String getType() {
+ return (_type != null ? _type : "");
+ }
+
+ /**
+ * Returns the key for this entry. The key is the lower case name.
+ *
+ * @return key for this entry
+ */
+ public String getKey() {
+ return (_key != null ? _key : "");
+ }
+
+ /**
+ * @return record type
+ */
+ public DNSRecordType getRecordType() {
+ return (_recordType != null ? _recordType : DNSRecordType.TYPE_IGNORE);
+ }
+
+ /**
+ * @return record class
+ */
+ public DNSRecordClass getRecordClass() {
+ return (_dnsClass != null ? _dnsClass : DNSRecordClass.CLASS_UNKNOWN);
+ }
+
+ /**
+ * @return true if unique
+ */
+ public boolean isUnique() {
+ return _unique;
+ }
+
+ public Map<Fields, String> getQualifiedNameMap() {
+ return Collections.unmodifiableMap(_qualifiedNameMap);
+ }
+
+ public boolean isServicesDiscoveryMetaQuery() {
+ return _qualifiedNameMap.get(Fields.Application).equals("dns-sd") && _qualifiedNameMap.get(Fields.Instance).equals("_services");
+ }
+
+ public boolean isDomainDiscoveryQuery() {
+ // b._dns-sd._udp.<domain>.
+ // db._dns-sd._udp.<domain>.
+ // r._dns-sd._udp.<domain>.
+ // dr._dns-sd._udp.<domain>.
+ // lb._dns-sd._udp.<domain>.
+
+ if (_qualifiedNameMap.get(Fields.Application).equals("dns-sd")) {
+ String name = _qualifiedNameMap.get(Fields.Instance);
+ return "b".equals(name) || "db".equals(name) || "r".equals(name) || "dr".equals(name) || "lb".equals(name);
+ }
+ return false;
+ }
+
+ public boolean isReverseLookup() {
+ return this.isV4ReverseLookup() || this.isV6ReverseLookup();
+ }
+
+ public boolean isV4ReverseLookup() {
+ return _qualifiedNameMap.get(Fields.Domain).endsWith("in-addr.arpa");
+ }
+
+ public boolean isV6ReverseLookup() {
+ return _qualifiedNameMap.get(Fields.Domain).endsWith("ip6.arpa");
+ }
+
+ /**
+ * Check if the record is stale, i.e. it has outlived more than half of its TTL.
+ *
+ * @param now
+ * update date
+ * @return <code>true</code> is the record is stale, <code>false</code> otherwise.
+ */
+ public abstract boolean isStale(long now);
+
+ /**
+ * Check if the record is expired.
+ *
+ * @param now
+ * update date
+ * @return <code>true</code> is the record is expired, <code>false</code> otherwise.
+ */
+ public abstract boolean isExpired(long now);
+
+ /**
+ * Check that 2 entries are of the same class.
+ *
+ * @param entry
+ * @return <code>true</code> is the two class are the same, <code>false</code> otherwise.
+ */
+ public boolean isSameRecordClass(DNSEntry entry) {
+ return (entry != null) && (entry.getRecordClass() == this.getRecordClass());
+ }
+
+ /**
+ * Check that 2 entries are of the same type.
+ *
+ * @param entry
+ * @return <code>true</code> is the two type are the same, <code>false</code> otherwise.
+ */
+ public boolean isSameType(DNSEntry entry) {
+ return (entry != null) && (entry.getRecordType() == this.getRecordType());
+ }
+
+ /**
+ * @param dout
+ * @exception IOException
+ */
+ protected void toByteArray(DataOutputStream dout) throws IOException {
+ dout.write(this.getName().getBytes("UTF8"));
+ dout.writeShort(this.getRecordType().indexValue());
+ dout.writeShort(this.getRecordClass().indexValue());
+ }
+
+ /**
+ * Creates a byte array representation of this record. This is needed for tie-break tests according to draft-cheshire-dnsext-multicastdns-04.txt chapter 9.2.
+ *
+ * @return byte array representation
+ */
+ protected byte[] toByteArray() {
+ try {
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ DataOutputStream dout = new DataOutputStream(bout);
+ this.toByteArray(dout);
+ dout.close();
+ return bout.toByteArray();
+ } catch (IOException e) {
+ throw new InternalError();
+ }
+ }
+
+ /**
+ * Does a lexicographic comparison of the byte array representation of this record and that record. This is needed for tie-break tests according to draft-cheshire-dnsext-multicastdns-04.txt chapter 9.2.
+ *
+ * @param that
+ * @return a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.
+ */
+ public int compareTo(DNSEntry that) {
+ byte[] thisBytes = this.toByteArray();
+ byte[] thatBytes = that.toByteArray();
+ for (int i = 0, n = Math.min(thisBytes.length, thatBytes.length); i < n; i++) {
+ if (thisBytes[i] > thatBytes[i]) {
+ return 1;
+ } else if (thisBytes[i] < thatBytes[i]) {
+ return -1;
+ }
+ }
+ return thisBytes.length - thatBytes.length;
+ }
+
+ /**
+ * Overriden, to return a value which is consistent with the value returned by equals(Object).
+ */
+ @Override
+ public int hashCode() {
+ return this.getKey().hashCode() + this.getRecordType().indexValue() + this.getRecordClass().indexValue();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ StringBuilder aLog = new StringBuilder(200);
+ aLog.append("[" + this.getClass().getSimpleName() + "@" + System.identityHashCode(this));
+ aLog.append(" type: " + this.getRecordType());
+ aLog.append(", class: " + this.getRecordClass());
+ aLog.append((_unique ? "-unique," : ","));
+ aLog.append(" name: " + _name);
+ this.toString(aLog);
+ aLog.append("]");
+ return aLog.toString();
+ }
+
+ /**
+ * @param aLog
+ */
+ protected void toString(StringBuilder aLog) {
+ // Stub
+ }
+
+}