| // Copyright 2003-2005 Arthur van Hoff, Rick Blair |
| // Licensed under Apache License version 2.0 |
| // Original license LGPL |
| |
| package javax.jmdns.impl; |
| |
| import java.net.InetAddress; |
| import java.util.Set; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| |
| import javax.jmdns.ServiceInfo; |
| import javax.jmdns.ServiceInfo.Fields; |
| import javax.jmdns.impl.JmDNSImpl.ServiceTypeEntry; |
| import javax.jmdns.impl.constants.DNSConstants; |
| import javax.jmdns.impl.constants.DNSRecordClass; |
| import javax.jmdns.impl.constants.DNSRecordType; |
| |
| /** |
| * A DNS question. |
| * |
| * @author Arthur van Hoff, Pierre Frisch |
| */ |
| public class DNSQuestion extends DNSEntry { |
| private static Logger logger = Logger.getLogger(DNSQuestion.class.getName()); |
| |
| /** |
| * Address question. |
| */ |
| private static class DNS4Address extends DNSQuestion { |
| DNS4Address(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) { |
| super(name, type, recordClass, unique); |
| } |
| |
| @Override |
| public void addAnswers(JmDNSImpl jmDNSImpl, Set<DNSRecord> answers) { |
| DNSRecord answer = jmDNSImpl.getLocalHost().getDNSAddressRecord(this.getRecordType(), DNSRecordClass.UNIQUE, DNSConstants.DNS_TTL); |
| if (answer != null) { |
| answers.add(answer); |
| } |
| } |
| |
| @Override |
| public boolean iAmTheOnlyOne(JmDNSImpl jmDNSImpl) { |
| String name = this.getName().toLowerCase(); |
| return jmDNSImpl.getLocalHost().getName().equals(name) || jmDNSImpl.getServices().keySet().contains(name); |
| } |
| |
| } |
| |
| /** |
| * Address question. |
| */ |
| private static class DNS6Address extends DNSQuestion { |
| DNS6Address(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) { |
| super(name, type, recordClass, unique); |
| } |
| |
| @Override |
| public void addAnswers(JmDNSImpl jmDNSImpl, Set<DNSRecord> answers) { |
| DNSRecord answer = jmDNSImpl.getLocalHost().getDNSAddressRecord(this.getRecordType(), DNSRecordClass.UNIQUE, DNSConstants.DNS_TTL); |
| if (answer != null) { |
| answers.add(answer); |
| } |
| } |
| |
| @Override |
| public boolean iAmTheOnlyOne(JmDNSImpl jmDNSImpl) { |
| String name = this.getName().toLowerCase(); |
| return jmDNSImpl.getLocalHost().getName().equals(name) || jmDNSImpl.getServices().keySet().contains(name); |
| } |
| |
| } |
| |
| /** |
| * Host Information question. |
| */ |
| private static class HostInformation extends DNSQuestion { |
| HostInformation(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) { |
| super(name, type, recordClass, unique); |
| } |
| } |
| |
| /** |
| * Pointer question. |
| */ |
| private static class Pointer extends DNSQuestion { |
| Pointer(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) { |
| super(name, type, recordClass, unique); |
| } |
| |
| @Override |
| public void addAnswers(JmDNSImpl jmDNSImpl, Set<DNSRecord> answers) { |
| // find matching services |
| for (ServiceInfo serviceInfo : jmDNSImpl.getServices().values()) { |
| this.addAnswersForServiceInfo(jmDNSImpl, answers, (ServiceInfoImpl) serviceInfo); |
| } |
| if (this.isServicesDiscoveryMetaQuery()) { |
| for (String serviceType : jmDNSImpl.getServiceTypes().keySet()) { |
| ServiceTypeEntry typeEntry = jmDNSImpl.getServiceTypes().get(serviceType); |
| answers.add(new DNSRecord.Pointer("_services._dns-sd._udp.local.", DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE, DNSConstants.DNS_TTL, typeEntry.getType())); |
| } |
| } else if (this.isReverseLookup()) { |
| String ipValue = this.getQualifiedNameMap().get(Fields.Instance); |
| if ((ipValue != null) && (ipValue.length() > 0)) { |
| InetAddress address = jmDNSImpl.getLocalHost().getInetAddress(); |
| String hostIPAddress = (address != null ? address.getHostAddress() : ""); |
| if (ipValue.equalsIgnoreCase(hostIPAddress)) { |
| if (this.isV4ReverseLookup()) { |
| answers.add(jmDNSImpl.getLocalHost().getDNSReverseAddressRecord(DNSRecordType.TYPE_A, DNSRecordClass.NOT_UNIQUE, DNSConstants.DNS_TTL)); |
| } |
| if (this.isV6ReverseLookup()) { |
| answers.add(jmDNSImpl.getLocalHost().getDNSReverseAddressRecord(DNSRecordType.TYPE_AAAA, DNSRecordClass.NOT_UNIQUE, DNSConstants.DNS_TTL)); |
| } |
| } |
| } |
| } else if (this.isDomainDiscoveryQuery()) { |
| // FIXME [PJYF Nov 16 2010] We do not currently support domain discovery |
| } |
| } |
| |
| } |
| |
| /** |
| * Service question. |
| */ |
| private static class Service extends DNSQuestion { |
| Service(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) { |
| super(name, type, recordClass, unique); |
| } |
| |
| @Override |
| public void addAnswers(JmDNSImpl jmDNSImpl, Set<DNSRecord> answers) { |
| String loname = this.getName().toLowerCase(); |
| if (jmDNSImpl.getLocalHost().getName().equalsIgnoreCase(loname)) { |
| // type = DNSConstants.TYPE_A; |
| answers.addAll(jmDNSImpl.getLocalHost().answers(this.isUnique(), DNSConstants.DNS_TTL)); |
| return; |
| } |
| // Service type request |
| if (jmDNSImpl.getServiceTypes().containsKey(loname)) { |
| DNSQuestion question = new Pointer(this.getName(), DNSRecordType.TYPE_PTR, this.getRecordClass(), this.isUnique()); |
| question.addAnswers(jmDNSImpl, answers); |
| return; |
| } |
| |
| this.addAnswersForServiceInfo(jmDNSImpl, answers, (ServiceInfoImpl) jmDNSImpl.getServices().get(loname)); |
| } |
| |
| @Override |
| public boolean iAmTheOnlyOne(JmDNSImpl jmDNSImpl) { |
| String name = this.getName().toLowerCase(); |
| return jmDNSImpl.getLocalHost().getName().equals(name) || jmDNSImpl.getServices().keySet().contains(name); |
| } |
| |
| } |
| |
| /** |
| * Text question. |
| */ |
| private static class Text extends DNSQuestion { |
| Text(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) { |
| super(name, type, recordClass, unique); |
| } |
| |
| @Override |
| public void addAnswers(JmDNSImpl jmDNSImpl, Set<DNSRecord> answers) { |
| this.addAnswersForServiceInfo(jmDNSImpl, answers, (ServiceInfoImpl) jmDNSImpl.getServices().get(this.getName().toLowerCase())); |
| } |
| |
| @Override |
| public boolean iAmTheOnlyOne(JmDNSImpl jmDNSImpl) { |
| String name = this.getName().toLowerCase(); |
| return jmDNSImpl.getLocalHost().getName().equals(name) || jmDNSImpl.getServices().keySet().contains(name); |
| } |
| |
| } |
| |
| /** |
| * AllRecords question. |
| */ |
| private static class AllRecords extends DNSQuestion { |
| AllRecords(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) { |
| super(name, type, recordClass, unique); |
| } |
| |
| @Override |
| public boolean isSameType(DNSEntry entry) { |
| // We match all non null entry |
| return (entry != null); |
| } |
| |
| @Override |
| public void addAnswers(JmDNSImpl jmDNSImpl, Set<DNSRecord> answers) { |
| String loname = this.getName().toLowerCase(); |
| if (jmDNSImpl.getLocalHost().getName().equalsIgnoreCase(loname)) { |
| // type = DNSConstants.TYPE_A; |
| answers.addAll(jmDNSImpl.getLocalHost().answers(this.isUnique(), DNSConstants.DNS_TTL)); |
| return; |
| } |
| // Service type request |
| if (jmDNSImpl.getServiceTypes().containsKey(loname)) { |
| DNSQuestion question = new Pointer(this.getName(), DNSRecordType.TYPE_PTR, this.getRecordClass(), this.isUnique()); |
| question.addAnswers(jmDNSImpl, answers); |
| return; |
| } |
| |
| this.addAnswersForServiceInfo(jmDNSImpl, answers, (ServiceInfoImpl) jmDNSImpl.getServices().get(loname)); |
| } |
| |
| @Override |
| public boolean iAmTheOnlyOne(JmDNSImpl jmDNSImpl) { |
| String name = this.getName().toLowerCase(); |
| return jmDNSImpl.getLocalHost().getName().equals(name) || jmDNSImpl.getServices().keySet().contains(name); |
| } |
| |
| } |
| |
| DNSQuestion(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) { |
| super(name, type, recordClass, unique); |
| } |
| |
| /** |
| * Create a question. |
| * |
| * @param name |
| * DNS name to be resolved |
| * @param type |
| * Record type to resolve |
| * @param recordClass |
| * Record class to resolve |
| * @param unique |
| * Request unicast response (Currently not supported in this implementation) |
| * @return new question |
| */ |
| public static DNSQuestion newQuestion(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) { |
| switch (type) { |
| case TYPE_A: |
| return new DNS4Address(name, type, recordClass, unique); |
| case TYPE_A6: |
| return new DNS6Address(name, type, recordClass, unique); |
| case TYPE_AAAA: |
| return new DNS6Address(name, type, recordClass, unique); |
| case TYPE_ANY: |
| return new AllRecords(name, type, recordClass, unique); |
| case TYPE_HINFO: |
| return new HostInformation(name, type, recordClass, unique); |
| case TYPE_PTR: |
| return new Pointer(name, type, recordClass, unique); |
| case TYPE_SRV: |
| return new Service(name, type, recordClass, unique); |
| case TYPE_TXT: |
| return new Text(name, type, recordClass, unique); |
| default: |
| return new DNSQuestion(name, type, recordClass, unique); |
| } |
| } |
| |
| /** |
| * Check if this question is answered by a given DNS record. |
| */ |
| boolean answeredBy(DNSEntry rec) { |
| return this.isSameRecordClass(rec) && this.isSameType(rec) && this.getName().equals(rec.getName()); |
| } |
| |
| /** |
| * Adds answers to the list for our question. |
| * |
| * @param jmDNSImpl |
| * DNS holding the records |
| * @param answers |
| * List of previous answer to append. |
| */ |
| public void addAnswers(JmDNSImpl jmDNSImpl, Set<DNSRecord> answers) { |
| // By default we do nothing |
| } |
| |
| protected void addAnswersForServiceInfo(JmDNSImpl jmDNSImpl, Set<DNSRecord> answers, ServiceInfoImpl info) { |
| if ((info != null) && info.isAnnounced()) { |
| if (this.getName().equalsIgnoreCase(info.getQualifiedName()) || this.getName().equalsIgnoreCase(info.getType())) { |
| answers.addAll(jmDNSImpl.getLocalHost().answers(DNSRecordClass.UNIQUE, DNSConstants.DNS_TTL)); |
| answers.addAll(info.answers(DNSRecordClass.UNIQUE, DNSConstants.DNS_TTL, jmDNSImpl.getLocalHost())); |
| } |
| if (logger.isLoggable(Level.FINER)) { |
| logger.finer(jmDNSImpl.getName() + " DNSQuestion(" + this.getName() + ").addAnswersForServiceInfo(): info: " + info + "\n" + answers); |
| } |
| } |
| } |
| |
| /* |
| * (non-Javadoc) |
| * @see javax.jmdns.impl.DNSEntry#isStale(long) |
| */ |
| @Override |
| public boolean isStale(long now) { |
| return false; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * @see javax.jmdns.impl.DNSEntry#isExpired(long) |
| */ |
| @Override |
| public boolean isExpired(long now) { |
| return false; |
| } |
| |
| /** |
| * Checks if we are the only to be able to answer that question. |
| * |
| * @param jmDNSImpl |
| * DNS holding the records |
| * @return <code>true</code> if we are the only one with the answer to the question, <code>false</code> otherwise. |
| */ |
| public boolean iAmTheOnlyOne(JmDNSImpl jmDNSImpl) { |
| return false; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * @see javax.jmdns.impl.DNSEntry#toString(java.lang.StringBuilder) |
| */ |
| @Override |
| public void toString(StringBuilder aLog) { |
| // do nothing |
| } |
| |
| } |