13742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman// Copyright 2003-2005 Arthur van Hoff, Rick Blair
23742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman// Licensed under Apache License version 2.0
33742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman// Original license LGPL
43742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
53742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanpackage javax.jmdns.impl;
63742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
73742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport java.net.InetAddress;
83742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport java.util.Set;
93742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport java.util.logging.Level;
103742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport java.util.logging.Logger;
113742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
123742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport javax.jmdns.ServiceInfo;
133742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport javax.jmdns.ServiceInfo.Fields;
143742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport javax.jmdns.impl.JmDNSImpl.ServiceTypeEntry;
153742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport javax.jmdns.impl.constants.DNSConstants;
163742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport javax.jmdns.impl.constants.DNSRecordClass;
173742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport javax.jmdns.impl.constants.DNSRecordType;
183742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
193742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman/**
203742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * A DNS question.
213742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman *
223742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * @author Arthur van Hoff, Pierre Frisch
233742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman */
243742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanpublic class DNSQuestion extends DNSEntry {
253742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    private static Logger logger = Logger.getLogger(DNSQuestion.class.getName());
263742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
273742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
283742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * Address question.
293742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
303742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    private static class DNS4Address extends DNSQuestion {
313742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        DNS4Address(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) {
323742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            super(name, type, recordClass, unique);
333742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
343742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
353742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        @Override
363742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        public void addAnswers(JmDNSImpl jmDNSImpl, Set<DNSRecord> answers) {
373742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            DNSRecord answer = jmDNSImpl.getLocalHost().getDNSAddressRecord(this.getRecordType(), DNSRecordClass.UNIQUE, DNSConstants.DNS_TTL);
383742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            if (answer != null) {
393742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                answers.add(answer);
403742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            }
413742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
423742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
433742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        @Override
443742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        public boolean iAmTheOnlyOne(JmDNSImpl jmDNSImpl) {
453742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            String name = this.getName().toLowerCase();
463742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            return jmDNSImpl.getLocalHost().getName().equals(name) || jmDNSImpl.getServices().keySet().contains(name);
473742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
483742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
493742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
503742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
513742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
523742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * Address question.
533742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
543742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    private static class DNS6Address extends DNSQuestion {
553742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        DNS6Address(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) {
563742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            super(name, type, recordClass, unique);
573742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
583742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
593742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        @Override
603742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        public void addAnswers(JmDNSImpl jmDNSImpl, Set<DNSRecord> answers) {
613742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            DNSRecord answer = jmDNSImpl.getLocalHost().getDNSAddressRecord(this.getRecordType(), DNSRecordClass.UNIQUE, DNSConstants.DNS_TTL);
623742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            if (answer != null) {
633742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                answers.add(answer);
643742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            }
653742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
663742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
673742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        @Override
683742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        public boolean iAmTheOnlyOne(JmDNSImpl jmDNSImpl) {
693742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            String name = this.getName().toLowerCase();
703742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            return jmDNSImpl.getLocalHost().getName().equals(name) || jmDNSImpl.getServices().keySet().contains(name);
713742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
723742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
733742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
743742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
753742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
763742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * Host Information question.
773742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
783742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    private static class HostInformation extends DNSQuestion {
793742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        HostInformation(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) {
803742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            super(name, type, recordClass, unique);
813742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
823742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
833742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
843742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
853742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * Pointer question.
863742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
873742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    private static class Pointer extends DNSQuestion {
883742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        Pointer(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) {
893742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            super(name, type, recordClass, unique);
903742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
913742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
923742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        @Override
933742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        public void addAnswers(JmDNSImpl jmDNSImpl, Set<DNSRecord> answers) {
943742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            // find matching services
953742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            for (ServiceInfo serviceInfo : jmDNSImpl.getServices().values()) {
963742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                this.addAnswersForServiceInfo(jmDNSImpl, answers, (ServiceInfoImpl) serviceInfo);
973742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            }
983742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            if (this.isServicesDiscoveryMetaQuery()) {
993742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                for (String serviceType : jmDNSImpl.getServiceTypes().keySet()) {
1003742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                    ServiceTypeEntry typeEntry = jmDNSImpl.getServiceTypes().get(serviceType);
1013742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                    answers.add(new DNSRecord.Pointer("_services._dns-sd._udp.local.", DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE, DNSConstants.DNS_TTL, typeEntry.getType()));
1023742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                }
1033742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            } else if (this.isReverseLookup()) {
1043742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                String ipValue = this.getQualifiedNameMap().get(Fields.Instance);
1053742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                if ((ipValue != null) && (ipValue.length() > 0)) {
1063742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                    InetAddress address = jmDNSImpl.getLocalHost().getInetAddress();
1073742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                    String hostIPAddress = (address != null ? address.getHostAddress() : "");
1083742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                    if (ipValue.equalsIgnoreCase(hostIPAddress)) {
1093742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                        if (this.isV4ReverseLookup()) {
1103742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                            answers.add(jmDNSImpl.getLocalHost().getDNSReverseAddressRecord(DNSRecordType.TYPE_A, DNSRecordClass.NOT_UNIQUE, DNSConstants.DNS_TTL));
1113742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                        }
1123742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                        if (this.isV6ReverseLookup()) {
1133742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                            answers.add(jmDNSImpl.getLocalHost().getDNSReverseAddressRecord(DNSRecordType.TYPE_AAAA, DNSRecordClass.NOT_UNIQUE, DNSConstants.DNS_TTL));
1143742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                        }
1153742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                    }
1163742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                }
1173742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            } else if (this.isDomainDiscoveryQuery()) {
1183742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                // FIXME [PJYF Nov 16 2010] We do not currently support domain discovery
1193742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            }
1203742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
1213742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1223742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
1233742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1243742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
1253742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * Service question.
1263742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
1273742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    private static class Service extends DNSQuestion {
1283742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        Service(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) {
1293742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            super(name, type, recordClass, unique);
1303742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
1313742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1323742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        @Override
1333742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        public void addAnswers(JmDNSImpl jmDNSImpl, Set<DNSRecord> answers) {
1343742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            String loname = this.getName().toLowerCase();
1353742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            if (jmDNSImpl.getLocalHost().getName().equalsIgnoreCase(loname)) {
1363742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                // type = DNSConstants.TYPE_A;
1373742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                answers.addAll(jmDNSImpl.getLocalHost().answers(this.isUnique(), DNSConstants.DNS_TTL));
1383742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                return;
1393742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            }
1403742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            // Service type request
1413742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            if (jmDNSImpl.getServiceTypes().containsKey(loname)) {
1423742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                DNSQuestion question = new Pointer(this.getName(), DNSRecordType.TYPE_PTR, this.getRecordClass(), this.isUnique());
1433742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                question.addAnswers(jmDNSImpl, answers);
1443742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                return;
1453742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            }
1463742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1473742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            this.addAnswersForServiceInfo(jmDNSImpl, answers, (ServiceInfoImpl) jmDNSImpl.getServices().get(loname));
1483742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
1493742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1503742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        @Override
1513742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        public boolean iAmTheOnlyOne(JmDNSImpl jmDNSImpl) {
1523742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            String name = this.getName().toLowerCase();
1533742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            return jmDNSImpl.getLocalHost().getName().equals(name) || jmDNSImpl.getServices().keySet().contains(name);
1543742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
1553742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1563742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
1573742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1583742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
1593742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * Text question.
1603742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
1613742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    private static class Text extends DNSQuestion {
1623742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        Text(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) {
1633742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            super(name, type, recordClass, unique);
1643742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
1653742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1663742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        @Override
1673742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        public void addAnswers(JmDNSImpl jmDNSImpl, Set<DNSRecord> answers) {
1683742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            this.addAnswersForServiceInfo(jmDNSImpl, answers, (ServiceInfoImpl) jmDNSImpl.getServices().get(this.getName().toLowerCase()));
1693742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
1703742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1713742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        @Override
1723742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        public boolean iAmTheOnlyOne(JmDNSImpl jmDNSImpl) {
1733742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            String name = this.getName().toLowerCase();
1743742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            return jmDNSImpl.getLocalHost().getName().equals(name) || jmDNSImpl.getServices().keySet().contains(name);
1753742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
1763742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1773742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
1783742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1793742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
1803742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * AllRecords question.
1813742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
1823742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    private static class AllRecords extends DNSQuestion {
1833742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        AllRecords(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) {
1843742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            super(name, type, recordClass, unique);
1853742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
1863742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1873742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        @Override
1883742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        public boolean isSameType(DNSEntry entry) {
1893742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            // We match all non null entry
1903742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            return (entry != null);
1913742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
1923742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1933742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        @Override
1943742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        public void addAnswers(JmDNSImpl jmDNSImpl, Set<DNSRecord> answers) {
1953742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            String loname = this.getName().toLowerCase();
1963742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            if (jmDNSImpl.getLocalHost().getName().equalsIgnoreCase(loname)) {
1973742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                // type = DNSConstants.TYPE_A;
1983742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                answers.addAll(jmDNSImpl.getLocalHost().answers(this.isUnique(), DNSConstants.DNS_TTL));
1993742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                return;
2003742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            }
2013742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            // Service type request
2023742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            if (jmDNSImpl.getServiceTypes().containsKey(loname)) {
2033742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                DNSQuestion question = new Pointer(this.getName(), DNSRecordType.TYPE_PTR, this.getRecordClass(), this.isUnique());
2043742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                question.addAnswers(jmDNSImpl, answers);
2053742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                return;
2063742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            }
2073742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
2083742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            this.addAnswersForServiceInfo(jmDNSImpl, answers, (ServiceInfoImpl) jmDNSImpl.getServices().get(loname));
2093742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
2103742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
2113742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        @Override
2123742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        public boolean iAmTheOnlyOne(JmDNSImpl jmDNSImpl) {
2133742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            String name = this.getName().toLowerCase();
2143742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            return jmDNSImpl.getLocalHost().getName().equals(name) || jmDNSImpl.getServices().keySet().contains(name);
2153742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
2163742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
2173742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
2183742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
2193742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    DNSQuestion(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) {
2203742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        super(name, type, recordClass, unique);
2213742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
2223742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
2233742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
2243742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * Create a question.
2253742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     *
2263742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @param name
2273742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     *            DNS name to be resolved
2283742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @param type
2293742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     *            Record type to resolve
2303742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @param recordClass
2313742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     *            Record class to resolve
2323742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @param unique
2333742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     *            Request unicast response (Currently not supported in this implementation)
2343742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @return new question
2353742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
2363742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public static DNSQuestion newQuestion(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) {
2373742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        switch (type) {
2383742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            case TYPE_A:
2393742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                return new DNS4Address(name, type, recordClass, unique);
2403742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            case TYPE_A6:
2413742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                return new DNS6Address(name, type, recordClass, unique);
2423742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            case TYPE_AAAA:
2433742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                return new DNS6Address(name, type, recordClass, unique);
2443742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            case TYPE_ANY:
2453742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                return new AllRecords(name, type, recordClass, unique);
2463742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            case TYPE_HINFO:
2473742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                return new HostInformation(name, type, recordClass, unique);
2483742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            case TYPE_PTR:
2493742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                return new Pointer(name, type, recordClass, unique);
2503742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            case TYPE_SRV:
2513742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                return new Service(name, type, recordClass, unique);
2523742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            case TYPE_TXT:
2533742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                return new Text(name, type, recordClass, unique);
2543742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            default:
2553742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                return new DNSQuestion(name, type, recordClass, unique);
2563742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
2573742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
2583742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
2593742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
2603742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * Check if this question is answered by a given DNS record.
2613742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
2623742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    boolean answeredBy(DNSEntry rec) {
2633742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return this.isSameRecordClass(rec) && this.isSameType(rec) && this.getName().equals(rec.getName());
2643742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
2653742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
2663742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
2673742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * Adds answers to the list for our question.
2683742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     *
2693742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @param jmDNSImpl
2703742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     *            DNS holding the records
2713742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @param answers
2723742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     *            List of previous answer to append.
2733742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
2743742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public void addAnswers(JmDNSImpl jmDNSImpl, Set<DNSRecord> answers) {
2753742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        // By default we do nothing
2763742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
2773742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
2783742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    protected void addAnswersForServiceInfo(JmDNSImpl jmDNSImpl, Set<DNSRecord> answers, ServiceInfoImpl info) {
2793742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        if ((info != null) && info.isAnnounced()) {
2803742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            if (this.getName().equalsIgnoreCase(info.getQualifiedName()) || this.getName().equalsIgnoreCase(info.getType())) {
2813742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                answers.addAll(jmDNSImpl.getLocalHost().answers(DNSRecordClass.UNIQUE, DNSConstants.DNS_TTL));
2823742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                answers.addAll(info.answers(DNSRecordClass.UNIQUE, DNSConstants.DNS_TTL, jmDNSImpl.getLocalHost()));
2833742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            }
2843742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            if (logger.isLoggable(Level.FINER)) {
2853742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                logger.finer(jmDNSImpl.getName() + " DNSQuestion(" + this.getName() + ").addAnswersForServiceInfo(): info: " + info + "\n" + answers);
2863742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            }
2873742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
2883742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
2893742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
2903742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /*
2913742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * (non-Javadoc)
2923742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @see javax.jmdns.impl.DNSEntry#isStale(long)
2933742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
2943742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    @Override
2953742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public boolean isStale(long now) {
2963742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return false;
2973742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
2983742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
2993742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /*
3003742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * (non-Javadoc)
3013742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @see javax.jmdns.impl.DNSEntry#isExpired(long)
3023742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
3033742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    @Override
3043742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public boolean isExpired(long now) {
3053742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return false;
3063742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
3073742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
3083742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
3093742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * Checks if we are the only to be able to answer that question.
3103742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     *
3113742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @param jmDNSImpl
3123742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     *            DNS holding the records
3133742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @return <code>true</code> if we are the only one with the answer to the question, <code>false</code> otherwise.
3143742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
3153742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public boolean iAmTheOnlyOne(JmDNSImpl jmDNSImpl) {
3163742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return false;
3173742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
3183742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
3193742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /*
3203742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * (non-Javadoc)
3213742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @see javax.jmdns.impl.DNSEntry#toString(java.lang.StringBuilder)
3223742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
3233742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    @Override
3243742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public void toString(StringBuilder aLog) {
3253742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        // do nothing
3263742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
3273742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
3283742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman}