// /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.MulticastSocket;
import java.net.SocketException;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.jmdns.JmDNS;
import javax.jmdns.ServiceEvent;
import javax.jmdns.ServiceInfo;
import javax.jmdns.ServiceInfo.Fields;
import javax.jmdns.ServiceListener;
import javax.jmdns.ServiceTypeListener;
import javax.jmdns.impl.ListenerStatus.ServiceListenerStatus;
import javax.jmdns.impl.ListenerStatus.ServiceTypeListenerStatus;
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;

// REMIND: multiple IP addresses

/**
 * mDNS implementation in Java.
 *
 * @author Arthur van Hoff, Rick Blair, Jeff Sonstein, Werner Randelshofer, Pierre Frisch, Scott Lewis
 */
public class JmDNSImpl extends JmDNS implements DNSStatefulObject, DNSTaskStarter {
    private static Logger logger = Logger.getLogger(JmDNSImpl.class.getName());

    public enum Operation {
        Remove, Update, Add, RegisterServiceType, Noop
    }

    /**
     * This is the multicast group, we are listening to for multicast DNS messages.
     */
    private volatile InetAddress                                     _group;
    /**
     * This is our multicast socket.
     */
    private volatile MulticastSocket                                 _socket;

    /**
     * Holds instances of JmDNS.DNSListener. Must by a synchronized collection, because it is updated from concurrent threads.
     */
    private final List<DNSListener>                                  _listeners;

    /**
     * Holds instances of ServiceListener's. Keys are Strings holding a fully qualified service type. Values are LinkedList's of ServiceListener's.
     */
    private final ConcurrentMap<String, List<ServiceListenerStatus>> _serviceListeners;

    /**
     * Holds instances of ServiceTypeListener's.
     */
    private final Set<ServiceTypeListenerStatus>                     _typeListeners;

    /**
     * Cache for DNSEntry's.
     */
    private final DNSCache                                           _cache;

    /**
     * This hashtable holds the services that have been registered. Keys are instances of String which hold an all lower-case version of the fully qualified service name. Values are instances of ServiceInfo.
     */
    private final ConcurrentMap<String, ServiceInfo>                 _services;

    /**
     * This hashtable holds the service types that have been registered or that have been received in an incoming datagram.<br/>
     * Keys are instances of String which hold an all lower-case version of the fully qualified service type.<br/>
     * Values hold the fully qualified service type.
     */
    private final ConcurrentMap<String, ServiceTypeEntry>            _serviceTypes;

    private volatile Delegate                                        _delegate;

    /**
     * This is used to store type entries. The type is stored as a call variable and the map support the subtypes.
     * <p>
     * The key is the lowercase version as the value is the case preserved version.
     * </p>
     */
    public static class ServiceTypeEntry extends AbstractMap<String, String> implements Cloneable {

        private final Set<Map.Entry<String, String>> _entrySet;

        private final String                         _type;

        private static class SubTypeEntry implements Entry<String, String>, java.io.Serializable, Cloneable {

            private static final long serialVersionUID = 9188503522395855322L;

            private final String      _key;
            private final String      _value;

            public SubTypeEntry(String subtype) {
                super();
                _value = (subtype != null ? subtype : "");
                _key = _value.toLowerCase();
            }

            /**
             * {@inheritDoc}
             */
            @Override
            public String getKey() {
                return _key;
            }

            /**
             * {@inheritDoc}
             */
            @Override
            public String getValue() {
                return _value;
            }

            /**
             * Replaces the value corresponding to this entry with the specified value (optional operation). This implementation simply throws <tt>UnsupportedOperationException</tt>, as this class implements an <i>immutable</i> map entry.
             *
             * @param value
             *            new value to be stored in this entry
             * @return (Does not return)
             * @exception UnsupportedOperationException
             *                always
             */
            @Override
            public String setValue(String value) {
                throw new UnsupportedOperationException();
            }

            /**
             * {@inheritDoc}
             */
            @Override
            public boolean equals(Object entry) {
                if (!(entry instanceof Map.Entry)) {
                    return false;
                }
                return this.getKey().equals(((Map.Entry<?, ?>) entry).getKey()) && this.getValue().equals(((Map.Entry<?, ?>) entry).getValue());
            }

            /**
             * {@inheritDoc}
             */
            @Override
            public int hashCode() {
                return (_key == null ? 0 : _key.hashCode()) ^ (_value == null ? 0 : _value.hashCode());
            }

            /*
             * (non-Javadoc)
             * @see java.lang.Object#clone()
             */
            @Override
            public SubTypeEntry clone() {
                // Immutable object
                return this;
            }

            /**
             * {@inheritDoc}
             */
            @Override
            public String toString() {
                return _key + "=" + _value;
            }

        }

        public ServiceTypeEntry(String type) {
            super();
            this._type = type;
            this._entrySet = new HashSet<Map.Entry<String, String>>();
        }

        /**
         * The type associated with this entry.
         *
         * @return the type
         */
        public String getType() {
            return _type;
        }

        /*
         * (non-Javadoc)
         * @see java.util.AbstractMap#entrySet()
         */
        @Override
        public Set<Map.Entry<String, String>> entrySet() {
            return _entrySet;
        }

        /**
         * Returns <code>true</code> if this set contains the specified element. More formally, returns <code>true</code> if and only if this set contains an element <code>e</code> such that
         * <code>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</code>.
         *
         * @param subtype
         *            element whose presence in this set is to be tested
         * @return <code>true</code> if this set contains the specified element
         */
        public boolean contains(String subtype) {
            return subtype != null && this.containsKey(subtype.toLowerCase());
        }

        /**
         * Adds the specified element to this set if it is not already present. More formally, adds the specified element <code>e</code> to this set if this set contains no element <code>e2</code> such that
         * <code>(e==null&nbsp;?&nbsp;e2==null&nbsp;:&nbsp;e.equals(e2))</code>. If this set already contains the element, the call leaves the set unchanged and returns <code>false</code>.
         *
         * @param subtype
         *            element to be added to this set
         * @return <code>true</code> if this set did not already contain the specified element
         */
        public boolean add(String subtype) {
            if (subtype == null || this.contains(subtype)) {
                return false;
            }
            _entrySet.add(new SubTypeEntry(subtype));
            return true;
        }

        /**
         * Returns an iterator over the elements in this set. The elements are returned in no particular order (unless this set is an instance of some class that provides a guarantee).
         *
         * @return an iterator over the elements in this set
         */
        public Iterator<String> iterator() {
            return this.keySet().iterator();
        }

        /*
         * (non-Javadoc)
         * @see java.util.AbstractMap#clone()
         */
        @Override
        public ServiceTypeEntry clone() {
            ServiceTypeEntry entry = new ServiceTypeEntry(this.getType());
            for (Map.Entry<String, String> subTypeEntry : this.entrySet()) {
                entry.add(subTypeEntry.getValue());
            }
            return entry;
        }

        /*
         * (non-Javadoc)
         * @see java.util.AbstractMap#toString()
         */
        @Override
        public String toString() {
            final StringBuilder aLog = new StringBuilder(200);
            if (this.isEmpty()) {
                aLog.append("empty");
            } else {
                for (String value : this.values()) {
                    aLog.append(value);
                    aLog.append(", ");
                }
                aLog.setLength(aLog.length() - 2);
            }
            return aLog.toString();
        }

    }

    /**
     * This is the shutdown hook, we registered with the java runtime.
     */
    protected Thread                                      _shutdown;

    /**
     * Handle on the local host
     */
    private HostInfo                                      _localHost;

    private Thread                                        _incomingListener;

    /**
     * Throttle count. This is used to count the overall number of probes sent by JmDNS. When the last throttle increment happened .
     */
    private int                                           _throttle;

    /**
     * Last throttle increment.
     */
    private long                                          _lastThrottleIncrement;

    private final ExecutorService                         _executor = Executors.newSingleThreadExecutor();

    //
    // 2009-09-16 ldeck: adding docbug patch with slight ammendments
    // 'Fixes two deadlock conditions involving JmDNS.close() - ID: 1473279'
    //
    // ---------------------------------------------------
    /**
     * The timer that triggers our announcements. We can't use the main timer object, because that could cause a deadlock where Prober waits on JmDNS.this lock held by close(), close() waits for us to finish, and we wait for Prober to give us back
     * the timer thread so we can announce. (Patch from docbug in 2006-04-19 still wasn't patched .. so I'm doing it!)
     */
    // private final Timer _cancelerTimer;
    // ---------------------------------------------------

    /**
     * The source for random values. This is used to introduce random delays in responses. This reduces the potential for collisions on the network.
     */
    private final static Random                           _random   = new Random();

    /**
     * This lock is used to coordinate processing of incoming and outgoing messages. This is needed, because the Rendezvous Conformance Test does not forgive race conditions.
     */
    private final ReentrantLock                           _ioLock   = new ReentrantLock();

    /**
     * If an incoming package which needs an answer is truncated, we store it here. We add more incoming DNSRecords to it, until the JmDNS.Responder timer picks it up.<br/>
     * FIXME [PJYF June 8 2010]: This does not work well with multiple planned answers for packages that came in from different clients.
     */
    private DNSIncoming                                   _plannedAnswer;

    // State machine

    /**
     * This hashtable is used to maintain a list of service types being collected by this JmDNS instance. The key of the hashtable is a service type name, the value is an instance of JmDNS.ServiceCollector.
     *
     * @see #list
     */
    private final ConcurrentMap<String, ServiceCollector> _serviceCollectors;

    private final String                                  _name;

    /**
     * Main method to display API information if run from java -jar
     *
     * @param argv
     *            the command line arguments
     */
    public static void main(String[] argv) {
        String version = null;
        try {
            final Properties pomProperties = new Properties();
            pomProperties.load(JmDNSImpl.class.getResourceAsStream("/META-INF/maven/javax.jmdns/jmdns/pom.properties"));
            version = pomProperties.getProperty("version");
        } catch (Exception e) {
            version = "RUNNING.IN.IDE.FULL";
        }
        System.out.println("JmDNS version \"" + version + "\"");
        System.out.println(" ");

        System.out.println("Running on java version \"" + System.getProperty("java.version") + "\"" + " (build " + System.getProperty("java.runtime.version") + ")" + " from " + System.getProperty("java.vendor"));

        System.out.println("Operating environment \"" + System.getProperty("os.name") + "\"" + " version " + System.getProperty("os.version") + " on " + System.getProperty("os.arch"));

        System.out.println("For more information on JmDNS please visit https://sourceforge.net/projects/jmdns/");
    }

    /**
     * Create an instance of JmDNS and bind it to a specific network interface given its IP-address.
     *
     * @param address
     *            IP address to bind to.
     * @param name
     *            name of the newly created JmDNS
     * @exception IOException
     */
    public JmDNSImpl(InetAddress address, String name) throws IOException {
        super();
        if (logger.isLoggable(Level.FINER)) {
            logger.finer("JmDNS instance created");
        }
        _cache = new DNSCache(100);

        _listeners = Collections.synchronizedList(new ArrayList<DNSListener>());
        _serviceListeners = new ConcurrentHashMap<String, List<ServiceListenerStatus>>();
        _typeListeners = Collections.synchronizedSet(new HashSet<ServiceTypeListenerStatus>());
        _serviceCollectors = new ConcurrentHashMap<String, ServiceCollector>();

        _services = new ConcurrentHashMap<String, ServiceInfo>(20);
        _serviceTypes = new ConcurrentHashMap<String, ServiceTypeEntry>(20);

        _localHost = HostInfo.newHostInfo(address, this, name);
        _name = (name != null ? name : _localHost.getName());

        // _cancelerTimer = new Timer("JmDNS.cancelerTimer");

        // (ldeck 2.1.1) preventing shutdown blocking thread
        // -------------------------------------------------
        // _shutdown = new Thread(new Shutdown(), "JmDNS.Shutdown");
        // Runtime.getRuntime().addShutdownHook(_shutdown);

        // -------------------------------------------------

        // Bind to multicast socket
        this.openMulticastSocket(this.getLocalHost());
        this.start(this.getServices().values());

        this.startReaper();
    }

    private void start(Collection<? extends ServiceInfo> serviceInfos) {
        if (_incomingListener == null) {
            _incomingListener = new SocketListener(this);
            _incomingListener.start();
        }
        this.startProber();
        for (ServiceInfo info : serviceInfos) {
            try {
                this.registerService(new ServiceInfoImpl(info));
            } catch (final Exception exception) {
                logger.log(Level.WARNING, "start() Registration exception ", exception);
            }
        }
    }

    private void openMulticastSocket(HostInfo hostInfo) throws IOException {
        if (_group == null) {
            if (hostInfo.getInetAddress() instanceof Inet6Address) {
                _group = InetAddress.getByName(DNSConstants.MDNS_GROUP_IPV6);
            } else {
                _group = InetAddress.getByName(DNSConstants.MDNS_GROUP);
            }
        }
        if (_socket != null) {
            this.closeMulticastSocket();
        }
        _socket = new MulticastSocket(DNSConstants.MDNS_PORT);
        if ((hostInfo != null) && (hostInfo.getInterface() != null)) {
            try {
                _socket.setNetworkInterface(hostInfo.getInterface());
            } catch (SocketException e) {
                if (logger.isLoggable(Level.FINE)) {
                    logger.fine("openMulticastSocket() Set network interface exception: " + e.getMessage());
                }
            }
        }
        _socket.setTimeToLive(255);
        _socket.joinGroup(_group);
    }

    private void closeMulticastSocket() {
        // jP: 20010-01-18. See below. We'll need this monitor...
        // assert (Thread.holdsLock(this));
        if (logger.isLoggable(Level.FINER)) {
            logger.finer("closeMulticastSocket()");
        }
        if (_socket != null) {
            // close socket
            try {
                try {
                    _socket.leaveGroup(_group);
                } catch (SocketException exception) {
                    //
                }
                _socket.close();
                // jP: 20010-01-18. It isn't safe to join() on the listener
                // thread - it attempts to lock the IoLock object, and deadlock
                // ensues. Per issue #2933183, changed this to wait on the JmDNS
                // monitor, checking on each notify (or timeout) that the
                // listener thread has stopped.
                //
                while (_incomingListener != null && _incomingListener.isAlive()) {
                    synchronized (this) {
                        try {
                            if (_incomingListener != null && _incomingListener.isAlive()) {
                                // wait time is arbitrary, we're really expecting notification.
                                if (logger.isLoggable(Level.FINER)) {
                                    logger.finer("closeMulticastSocket(): waiting for jmDNS monitor");
                                }
                                this.wait(1000);
                            }
                        } catch (InterruptedException ignored) {
                            // Ignored
                        }
                    }
                }
                _incomingListener = null;
            } catch (final Exception exception) {
                logger.log(Level.WARNING, "closeMulticastSocket() Close socket exception ", exception);
            }
            _socket = null;
        }
    }

    // State machine
    /**
     * {@inheritDoc}
     */
    @Override
    public boolean advanceState(DNSTask task) {
        return this._localHost.advanceState(task);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean revertState() {
        return this._localHost.revertState();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean cancelState() {
        return this._localHost.cancelState();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean closeState() {
        return this._localHost.closeState();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean recoverState() {
        return this._localHost.recoverState();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public JmDNSImpl getDns() {
        return this;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void associateWithTask(DNSTask task, DNSState state) {
        this._localHost.associateWithTask(task, state);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void removeAssociationWithTask(DNSTask task) {
        this._localHost.removeAssociationWithTask(task);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isAssociatedWithTask(DNSTask task, DNSState state) {
        return this._localHost.isAssociatedWithTask(task, state);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isProbing() {
        return this._localHost.isProbing();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isAnnouncing() {
        return this._localHost.isAnnouncing();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isAnnounced() {
        return this._localHost.isAnnounced();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isCanceling() {
        return this._localHost.isCanceling();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isCanceled() {
        return this._localHost.isCanceled();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isClosing() {
        return this._localHost.isClosing();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isClosed() {
        return this._localHost.isClosed();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean waitForAnnounced(long timeout) {
        return this._localHost.waitForAnnounced(timeout);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean waitForCanceled(long timeout) {
        return this._localHost.waitForCanceled(timeout);
    }

    /**
     * Return the DNSCache associated with the cache variable
     *
     * @return DNS cache
     */
    public DNSCache getCache() {
        return _cache;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getName() {
        return _name;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getHostName() {
        return _localHost.getName();
    }

    /**
     * Returns the local host info
     *
     * @return local host info
     */
    public HostInfo getLocalHost() {
        return _localHost;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public InetAddress getInetAddress() throws IOException {
        return _localHost.getInetAddress();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @Deprecated
    public InetAddress getInterface() throws IOException {
        return _socket.getInterface();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ServiceInfo getServiceInfo(String type, String name) {
        return this.getServiceInfo(type, name, false, DNSConstants.SERVICE_INFO_TIMEOUT);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ServiceInfo getServiceInfo(String type, String name, long timeout) {
        return this.getServiceInfo(type, name, false, timeout);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ServiceInfo getServiceInfo(String type, String name, boolean persistent) {
        return this.getServiceInfo(type, name, persistent, DNSConstants.SERVICE_INFO_TIMEOUT);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ServiceInfo getServiceInfo(String type, String name, boolean persistent, long timeout) {
        final ServiceInfoImpl info = this.resolveServiceInfo(type, name, "", persistent);
        this.waitForInfoData(info, timeout);
        return (info.hasData() ? info : null);
    }

    ServiceInfoImpl resolveServiceInfo(String type, String name, String subtype, boolean persistent) {
        this.cleanCache();
        String loType = type.toLowerCase();
        this.registerServiceType(type);
        if (_serviceCollectors.putIfAbsent(loType, new ServiceCollector(type)) == null) {
            this.addServiceListener(loType, _serviceCollectors.get(loType), ListenerStatus.SYNCHONEOUS);
        }

        // Check if the answer is in the cache.
        final ServiceInfoImpl info = this.getServiceInfoFromCache(type, name, subtype, persistent);
        // We still run the resolver to do the dispatch but if the info is already there it will quit immediately
        this.startServiceInfoResolver(info);

        return info;
    }

    ServiceInfoImpl getServiceInfoFromCache(String type, String name, String subtype, boolean persistent) {
        // Check if the answer is in the cache.
        ServiceInfoImpl info = new ServiceInfoImpl(type, name, subtype, 0, 0, 0, persistent, (byte[]) null);
        DNSEntry pointerEntry = this.getCache().getDNSEntry(new DNSRecord.Pointer(type, DNSRecordClass.CLASS_ANY, false, 0, info.getQualifiedName()));
        if (pointerEntry instanceof DNSRecord) {
            ServiceInfoImpl cachedInfo = (ServiceInfoImpl) ((DNSRecord) pointerEntry).getServiceInfo(persistent);
            if (cachedInfo != null) {
                // To get a complete info record we need to retrieve the service, address and the text bytes.

                Map<Fields, String> map = cachedInfo.getQualifiedNameMap();
                byte[] srvBytes = null;
                String server = "";
                DNSEntry serviceEntry = this.getCache().getDNSEntry(info.getQualifiedName(), DNSRecordType.TYPE_SRV, DNSRecordClass.CLASS_ANY);
                if (serviceEntry instanceof DNSRecord) {
                    ServiceInfo cachedServiceEntryInfo = ((DNSRecord) serviceEntry).getServiceInfo(persistent);
                    if (cachedServiceEntryInfo != null) {
                        cachedInfo = new ServiceInfoImpl(map, cachedServiceEntryInfo.getPort(), cachedServiceEntryInfo.getWeight(), cachedServiceEntryInfo.getPriority(), persistent, (byte[]) null);
                        srvBytes = cachedServiceEntryInfo.getTextBytes();
                        server = cachedServiceEntryInfo.getServer();
                    }
                }
                DNSEntry addressEntry = this.getCache().getDNSEntry(server, DNSRecordType.TYPE_A, DNSRecordClass.CLASS_ANY);
                if (addressEntry instanceof DNSRecord) {
                    ServiceInfo cachedAddressInfo = ((DNSRecord) addressEntry).getServiceInfo(persistent);
                    if (cachedAddressInfo != null) {
                        for (Inet4Address address : cachedAddressInfo.getInet4Addresses()) {
                            cachedInfo.addAddress(address);
                        }
                        cachedInfo._setText(cachedAddressInfo.getTextBytes());
                    }
                }
                addressEntry = this.getCache().getDNSEntry(server, DNSRecordType.TYPE_AAAA, DNSRecordClass.CLASS_ANY);
                if (addressEntry instanceof DNSRecord) {
                    ServiceInfo cachedAddressInfo = ((DNSRecord) addressEntry).getServiceInfo(persistent);
                    if (cachedAddressInfo != null) {
                        for (Inet6Address address : cachedAddressInfo.getInet6Addresses()) {
                            cachedInfo.addAddress(address);
                        }
                        cachedInfo._setText(cachedAddressInfo.getTextBytes());
                    }
                }
                DNSEntry textEntry = this.getCache().getDNSEntry(cachedInfo.getQualifiedName(), DNSRecordType.TYPE_TXT, DNSRecordClass.CLASS_ANY);
                if (textEntry instanceof DNSRecord) {
                    ServiceInfo cachedTextInfo = ((DNSRecord) textEntry).getServiceInfo(persistent);
                    if (cachedTextInfo != null) {
                        cachedInfo._setText(cachedTextInfo.getTextBytes());
                    }
                }
                if (cachedInfo.getTextBytes().length == 0) {
                    cachedInfo._setText(srvBytes);
                }
                if (cachedInfo.hasData()) {
                    info = cachedInfo;
                }
            }
        }
        return info;
    }

    private void waitForInfoData(ServiceInfo info, long timeout) {
        synchronized (info) {
            long loops = (timeout / 200L);
            if (loops < 1) {
                loops = 1;
            }
            for (int i = 0; i < loops; i++) {
                if (info.hasData()) {
                    break;
                }
                try {
                    info.wait(200);
                } catch (final InterruptedException e) {
                    /* Stub */
                }
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void requestServiceInfo(String type, String name) {
        this.requestServiceInfo(type, name, false, DNSConstants.SERVICE_INFO_TIMEOUT);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void requestServiceInfo(String type, String name, boolean persistent) {
        this.requestServiceInfo(type, name, persistent, DNSConstants.SERVICE_INFO_TIMEOUT);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void requestServiceInfo(String type, String name, long timeout) {
        this.requestServiceInfo(type, name, false, DNSConstants.SERVICE_INFO_TIMEOUT);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void requestServiceInfo(String type, String name, boolean persistent, long timeout) {
        final ServiceInfoImpl info = this.resolveServiceInfo(type, name, "", persistent);
        this.waitForInfoData(info, timeout);
    }

    void handleServiceResolved(ServiceEvent event) {
        List<ServiceListenerStatus> list = _serviceListeners.get(event.getType().toLowerCase());
        final List<ServiceListenerStatus> listCopy;
        if ((list != null) && (!list.isEmpty())) {
            if ((event.getInfo() != null) && event.getInfo().hasData()) {
                final ServiceEvent localEvent = event;
                synchronized (list) {
                    listCopy = new ArrayList<ServiceListenerStatus>(list);
                }
                for (final ServiceListenerStatus listener : listCopy) {
                    _executor.submit(new Runnable() {
                        /** {@inheritDoc} */
                        @Override
                        public void run() {
                            listener.serviceResolved(localEvent);
                        }
                    });
                }
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void addServiceTypeListener(ServiceTypeListener listener) throws IOException {
        ServiceTypeListenerStatus status = new ServiceTypeListenerStatus(listener, ListenerStatus.ASYNCHONEOUS);
        _typeListeners.add(status);

        // report cached service types
        for (String type : _serviceTypes.keySet()) {
            status.serviceTypeAdded(new ServiceEventImpl(this, type, "", null));
        }

        this.startTypeResolver();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void removeServiceTypeListener(ServiceTypeListener listener) {
        ServiceTypeListenerStatus status = new ServiceTypeListenerStatus(listener, ListenerStatus.ASYNCHONEOUS);
        _typeListeners.remove(status);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void addServiceListener(String type, ServiceListener listener) {
        this.addServiceListener(type, listener, ListenerStatus.ASYNCHONEOUS);
    }

    private void addServiceListener(String type, ServiceListener listener, boolean synch) {
        ServiceListenerStatus status = new ServiceListenerStatus(listener, synch);
        final String loType = type.toLowerCase();
        List<ServiceListenerStatus> list = _serviceListeners.get(loType);
        if (list == null) {
            if (_serviceListeners.putIfAbsent(loType, new LinkedList<ServiceListenerStatus>()) == null) {
                if (_serviceCollectors.putIfAbsent(loType, new ServiceCollector(type)) == null) {
                    // We have a problem here. The service collectors must be called synchronously so that their cache get cleaned up immediately or we will report .
                    this.addServiceListener(loType, _serviceCollectors.get(loType), ListenerStatus.SYNCHONEOUS);
                }
            }
            list = _serviceListeners.get(loType);
        }
        if (list != null) {
            synchronized (list) {
                if (!list.contains(listener)) {
                    list.add(status);
                }
            }
        }
        // report cached service types
        final List<ServiceEvent> serviceEvents = new ArrayList<ServiceEvent>();
        Collection<DNSEntry> dnsEntryLits = this.getCache().allValues();
        for (DNSEntry entry : dnsEntryLits) {
            final DNSRecord record = (DNSRecord) entry;
            if (record.getRecordType() == DNSRecordType.TYPE_SRV) {
                if (record.getKey().endsWith(loType)) {
                    // Do not used the record embedded method for generating event this will not work.
                    // serviceEvents.add(record.getServiceEvent(this));
                    serviceEvents.add(new ServiceEventImpl(this, record.getType(), toUnqualifiedName(record.getType(), record.getName()), record.getServiceInfo()));
                }
            }
        }
        // Actually call listener with all service events added above
        for (ServiceEvent serviceEvent : serviceEvents) {
            status.serviceAdded(serviceEvent);
        }
        // Create/start ServiceResolver
        this.startServiceResolver(type);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void removeServiceListener(String type, ServiceListener listener) {
        String loType = type.toLowerCase();
        List<ServiceListenerStatus> list = _serviceListeners.get(loType);
        if (list != null) {
            synchronized (list) {
                ServiceListenerStatus status = new ServiceListenerStatus(listener, ListenerStatus.ASYNCHONEOUS);
                list.remove(status);
                if (list.isEmpty()) {
                    _serviceListeners.remove(loType, list);
                }
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void registerService(ServiceInfo infoAbstract) throws IOException {
        if (this.isClosing() || this.isClosed()) {
            throw new IllegalStateException("This DNS is closed.");
        }
        final ServiceInfoImpl info = (ServiceInfoImpl) infoAbstract;

        if (info.getDns() != null) {
            if (info.getDns() != this) {
                throw new IllegalStateException("A service information can only be registered with a single instamce of JmDNS.");
            } else if (_services.get(info.getKey()) != null) {
                throw new IllegalStateException("A service information can only be registered once.");
            }
        }
        info.setDns(this);

        this.registerServiceType(info.getTypeWithSubtype());

        // bind the service to this address
        info.recoverState();
        info.setServer(_localHost.getName());
        info.addAddress(_localHost.getInet4Address());
        info.addAddress(_localHost.getInet6Address());

        this.waitForAnnounced(DNSConstants.SERVICE_INFO_TIMEOUT);

        this.makeServiceNameUnique(info);
        while (_services.putIfAbsent(info.getKey(), info) != null) {
            this.makeServiceNameUnique(info);
        }

        this.startProber();
        info.waitForAnnounced(DNSConstants.SERVICE_INFO_TIMEOUT);

        if (logger.isLoggable(Level.FINE)) {
            logger.fine("registerService() JmDNS registered service as " + info);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void unregisterService(ServiceInfo infoAbstract) {
        final ServiceInfoImpl info = (ServiceInfoImpl) _services.get(infoAbstract.getKey());

        if (info != null) {
            info.cancelState();
            this.startCanceler();
            info.waitForCanceled(DNSConstants.CLOSE_TIMEOUT);

            _services.remove(info.getKey(), info);
            if (logger.isLoggable(Level.FINE)) {
                logger.fine("unregisterService() JmDNS unregistered service as " + info);
            }
        } else {
            logger.warning("Removing unregistered service info: " + infoAbstract.getKey());
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void unregisterAllServices() {
        if (logger.isLoggable(Level.FINER)) {
            logger.finer("unregisterAllServices()");
        }

        for (String name : _services.keySet()) {
            ServiceInfoImpl info = (ServiceInfoImpl) _services.get(name);
            if (info != null) {
                if (logger.isLoggable(Level.FINER)) {
                    logger.finer("Cancelling service info: " + info);
                }
                info.cancelState();
            }
        }
        this.startCanceler();

        for (String name : _services.keySet()) {
            ServiceInfoImpl info = (ServiceInfoImpl) _services.get(name);
            if (info != null) {
                if (logger.isLoggable(Level.FINER)) {
                    logger.finer("Wait for service info cancel: " + info);
                }
                info.waitForCanceled(DNSConstants.CLOSE_TIMEOUT);
                _services.remove(name, info);
            }
        }

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean registerServiceType(String type) {
        boolean typeAdded = false;
        Map<Fields, String> map = ServiceInfoImpl.decodeQualifiedNameMapForType(type);
        String domain = map.get(Fields.Domain);
        String protocol = map.get(Fields.Protocol);
        String application = map.get(Fields.Application);
        String subtype = map.get(Fields.Subtype);

        final String name = (application.length() > 0 ? "_" + application + "." : "") + (protocol.length() > 0 ? "_" + protocol + "." : "") + domain + ".";
        final String loname = name.toLowerCase();
        if (logger.isLoggable(Level.FINE)) {
            logger.fine(this.getName() + ".registering service type: " + type + " as: " + name + (subtype.length() > 0 ? " subtype: " + subtype : ""));
        }
        if (!_serviceTypes.containsKey(loname) && !application.toLowerCase().equals("dns-sd") && !domain.toLowerCase().endsWith("in-addr.arpa") && !domain.toLowerCase().endsWith("ip6.arpa")) {
            typeAdded = _serviceTypes.putIfAbsent(loname, new ServiceTypeEntry(name)) == null;
            if (typeAdded) {
                final ServiceTypeListenerStatus[] list = _typeListeners.toArray(new ServiceTypeListenerStatus[_typeListeners.size()]);
                final ServiceEvent event = new ServiceEventImpl(this, name, "", null);
                for (final ServiceTypeListenerStatus status : list) {
                    _executor.submit(new Runnable() {
                        /** {@inheritDoc} */
                        @Override
                        public void run() {
                            status.serviceTypeAdded(event);
                        }
                    });
                }
            }
        }
        if (subtype.length() > 0) {
            ServiceTypeEntry subtypes = _serviceTypes.get(loname);
            if ((subtypes != null) && (!subtypes.contains(subtype))) {
                synchronized (subtypes) {
                    if (!subtypes.contains(subtype)) {
                        typeAdded = true;
                        subtypes.add(subtype);
                        final ServiceTypeListenerStatus[] list = _typeListeners.toArray(new ServiceTypeListenerStatus[_typeListeners.size()]);
                        final ServiceEvent event = new ServiceEventImpl(this, "_" + subtype + "._sub." + name, "", null);
                        for (final ServiceTypeListenerStatus status : list) {
                            _executor.submit(new Runnable() {
                                /** {@inheritDoc} */
                                @Override
                                public void run() {
                                    status.subTypeForServiceTypeAdded(event);
                                }
                            });
                        }
                    }
                }
            }
        }
        return typeAdded;
    }

    /**
     * Generate a possibly unique name for a service using the information we have in the cache.
     *
     * @return returns true, if the name of the service info had to be changed.
     */
    private boolean makeServiceNameUnique(ServiceInfoImpl info) {
        final String originalQualifiedName = info.getKey();
        final long now = System.currentTimeMillis();

        boolean collision;
        do {
            collision = false;

            // Check for collision in cache
            for (DNSEntry dnsEntry : this.getCache().getDNSEntryList(info.getKey())) {
                if (DNSRecordType.TYPE_SRV.equals(dnsEntry.getRecordType()) && !dnsEntry.isExpired(now)) {
                    final DNSRecord.Service s = (DNSRecord.Service) dnsEntry;
                    if (s.getPort() != info.getPort() || !s.getServer().equals(_localHost.getName())) {
                        if (logger.isLoggable(Level.FINER)) {
                            logger.finer("makeServiceNameUnique() JmDNS.makeServiceNameUnique srv collision:" + dnsEntry + " s.server=" + s.getServer() + " " + _localHost.getName() + " equals:" + (s.getServer().equals(_localHost.getName())));
                        }
                        info.setName(incrementName(info.getName()));
                        collision = true;
                        break;
                    }
                }
            }

            // Check for collision with other service infos published by JmDNS
            final ServiceInfo selfService = _services.get(info.getKey());
            if (selfService != null && selfService != info) {
                info.setName(incrementName(info.getName()));
                collision = true;
            }
        }
        while (collision);

        return !(originalQualifiedName.equals(info.getKey()));
    }

    String incrementName(String name) {
        String aName = name;
        try {
            final int l = aName.lastIndexOf('(');
            final int r = aName.lastIndexOf(')');
            if ((l >= 0) && (l < r)) {
                aName = aName.substring(0, l) + "(" + (Integer.parseInt(aName.substring(l + 1, r)) + 1) + ")";
            } else {
                aName += " (2)";
            }
        } catch (final NumberFormatException e) {
            aName += " (2)";
        }
        return aName;
    }

    /**
     * Add a listener for a question. The listener will receive updates of answers to the question as they arrive, or from the cache if they are already available.
     *
     * @param listener
     *            DSN listener
     * @param question
     *            DNS query
     */
    public void addListener(DNSListener listener, DNSQuestion question) {
        final long now = System.currentTimeMillis();

        // add the new listener
        _listeners.add(listener);

        // report existing matched records

        if (question != null) {
            for (DNSEntry dnsEntry : this.getCache().getDNSEntryList(question.getName().toLowerCase())) {
                if (question.answeredBy(dnsEntry) && !dnsEntry.isExpired(now)) {
                    listener.updateRecord(this.getCache(), now, dnsEntry);
                }
            }
        }
    }

    /**
     * Remove a listener from all outstanding questions. The listener will no longer receive any updates.
     *
     * @param listener
     *            DSN listener
     */
    public void removeListener(DNSListener listener) {
        _listeners.remove(listener);
    }

    /**
     * Renew a service when the record become stale. If there is no service collector for the type this method does nothing.
     *
     * @param record
     *            DNS record
     */
    public void renewServiceCollector(DNSRecord record) {
        ServiceInfo info = record.getServiceInfo();
        if (_serviceCollectors.containsKey(info.getType().toLowerCase())) {
            // Create/start ServiceResolver
            this.startServiceResolver(info.getType());
        }
    }

    // Remind: Method updateRecord should receive a better name.
    /**
     * Notify all listeners that a record was updated.
     *
     * @param now
     *            update date
     * @param rec
     *            DNS record
     * @param operation
     *            DNS cache operation
     */
    public void updateRecord(long now, DNSRecord rec, Operation operation) {
        // We do not want to block the entire DNS while we are updating the record for each listener (service info)
        {
            List<DNSListener> listenerList = null;
            synchronized (_listeners) {
                listenerList = new ArrayList<DNSListener>(_listeners);
            }
            for (DNSListener listener : listenerList) {
                listener.updateRecord(this.getCache(), now, rec);
            }
        }
        if (DNSRecordType.TYPE_PTR.equals(rec.getRecordType()))
        // if (DNSRecordType.TYPE_PTR.equals(rec.getRecordType()) || DNSRecordType.TYPE_SRV.equals(rec.getRecordType()))
        {
            ServiceEvent event = rec.getServiceEvent(this);
            if ((event.getInfo() == null) || !event.getInfo().hasData()) {
                // We do not care about the subtype because the info is only used if complete and the subtype will then be included.
                ServiceInfo info = this.getServiceInfoFromCache(event.getType(), event.getName(), "", false);
                if (info.hasData()) {
                    event = new ServiceEventImpl(this, event.getType(), event.getName(), info);
                }
            }

            List<ServiceListenerStatus> list = _serviceListeners.get(event.getType().toLowerCase());
            final List<ServiceListenerStatus> serviceListenerList;
            if (list != null) {
                synchronized (list) {
                    serviceListenerList = new ArrayList<ServiceListenerStatus>(list);
                }
            } else {
                serviceListenerList = Collections.emptyList();
            }
            if (logger.isLoggable(Level.FINEST)) {
                logger.finest(this.getName() + ".updating record for event: " + event + " list " + serviceListenerList + " operation: " + operation);
            }
            if (!serviceListenerList.isEmpty()) {
                final ServiceEvent localEvent = event;

                switch (operation) {
                    case Add:
                        for (final ServiceListenerStatus listener : serviceListenerList) {
                            if (listener.isSynchronous()) {
                                listener.serviceAdded(localEvent);
                            } else {
                                _executor.submit(new Runnable() {
                                    /** {@inheritDoc} */
                                    @Override
                                    public void run() {
                                        listener.serviceAdded(localEvent);
                                    }
                                });
                            }
                        }
                        break;
                    case Remove:
                        for (final ServiceListenerStatus listener : serviceListenerList) {
                            if (listener.isSynchronous()) {
                                listener.serviceRemoved(localEvent);
                            } else {
                                _executor.submit(new Runnable() {
                                    /** {@inheritDoc} */
                                    @Override
                                    public void run() {
                                        listener.serviceRemoved(localEvent);
                                    }
                                });
                            }
                        }
                        break;
                    default:
                        break;
                }
            }
        }
    }

    void handleRecord(DNSRecord record, long now) {
        DNSRecord newRecord = record;

        Operation cacheOperation = Operation.Noop;
        final boolean expired = newRecord.isExpired(now);
        if (logger.isLoggable(Level.FINE)) {
            logger.fine(this.getName() + " handle response: " + newRecord);
        }

        // update the cache
        if (!newRecord.isServicesDiscoveryMetaQuery() && !newRecord.isDomainDiscoveryQuery()) {
            final boolean unique = newRecord.isUnique();
            final DNSRecord cachedRecord = (DNSRecord) this.getCache().getDNSEntry(newRecord);
            if (logger.isLoggable(Level.FINE)) {
                logger.fine(this.getName() + " handle response cached record: " + cachedRecord);
            }
            if (unique) {
                for (DNSEntry entry : this.getCache().getDNSEntryList(newRecord.getKey())) {
                    if (newRecord.getRecordType().equals(entry.getRecordType()) && newRecord.getRecordClass().equals(entry.getRecordClass()) && (entry != cachedRecord)) {
                        ((DNSRecord) entry).setWillExpireSoon(now);
                    }
                }
            }
            if (cachedRecord != null) {
                if (expired) {
                    // if the record has a 0 ttl that means we have a cancel record we need to delay the removal by 1s
                    if (newRecord.getTTL() == 0) {
                        cacheOperation = Operation.Noop;
                        cachedRecord.setWillExpireSoon(now);
                        // the actual record will be disposed of by the record reaper.
                    } else {
                        cacheOperation = Operation.Remove;
                        this.getCache().removeDNSEntry(cachedRecord);
                    }
                } else {
                    // If the record content has changed we need to inform our listeners.
                    if (!newRecord.sameValue(cachedRecord) || (!newRecord.sameSubtype(cachedRecord) && (newRecord.getSubtype().length() > 0))) {
                        if (newRecord.isSingleValued()) {
                            cacheOperation = Operation.Update;
                            this.getCache().replaceDNSEntry(newRecord, cachedRecord);
                        } else {
                            // Address record can have more than one value on multi-homed machines
                            cacheOperation = Operation.Add;
                            this.getCache().addDNSEntry(newRecord);
                        }
                    } else {
                        cachedRecord.resetTTL(newRecord);
                        newRecord = cachedRecord;
                    }
                }
            } else {
                if (!expired) {
                    cacheOperation = Operation.Add;
                    this.getCache().addDNSEntry(newRecord);
                }
            }
        }

        // Register new service types
        if (newRecord.getRecordType() == DNSRecordType.TYPE_PTR) {
            // handle DNSConstants.DNS_META_QUERY records
            boolean typeAdded = false;
            if (newRecord.isServicesDiscoveryMetaQuery()) {
                // The service names are in the alias.
                if (!expired) {
                    typeAdded = this.registerServiceType(((DNSRecord.Pointer) newRecord).getAlias());
                }
                return;
            }
            typeAdded |= this.registerServiceType(newRecord.getName());
            if (typeAdded && (cacheOperation == Operation.Noop)) {
                cacheOperation = Operation.RegisterServiceType;
            }
        }

        // notify the listeners
        if (cacheOperation != Operation.Noop) {
            this.updateRecord(now, newRecord, cacheOperation);
        }

    }

    /**
     * Handle an incoming response. Cache answers, and pass them on to the appropriate questions.
     *
     * @exception IOException
     */
    void handleResponse(DNSIncoming msg) throws IOException {
        final long now = System.currentTimeMillis();

        boolean hostConflictDetected = false;
        boolean serviceConflictDetected = false;

        for (DNSRecord newRecord : msg.getAllAnswers()) {
            this.handleRecord(newRecord, now);

            if (DNSRecordType.TYPE_A.equals(newRecord.getRecordType()) || DNSRecordType.TYPE_AAAA.equals(newRecord.getRecordType())) {
                hostConflictDetected |= newRecord.handleResponse(this);
            } else {
                serviceConflictDetected |= newRecord.handleResponse(this);
            }

        }

        if (hostConflictDetected || serviceConflictDetected) {
            this.startProber();
        }
    }

    /**
     * Handle an incoming query. See if we can answer any part of it given our service infos.
     *
     * @param in
     * @param addr
     * @param port
     * @exception IOException
     */
    void handleQuery(DNSIncoming in, InetAddress addr, int port) throws IOException {
        if (logger.isLoggable(Level.FINE)) {
            logger.fine(this.getName() + ".handle query: " + in);
        }
        // Track known answers
        boolean conflictDetected = false;
        final long expirationTime = System.currentTimeMillis() + DNSConstants.KNOWN_ANSWER_TTL;
        for (DNSRecord answer : in.getAllAnswers()) {
            conflictDetected |= answer.handleQuery(this, expirationTime);
        }

        this.ioLock();
        try {

            if (_plannedAnswer != null) {
                _plannedAnswer.append(in);
            } else {
                DNSIncoming plannedAnswer = in.clone();
                if (in.isTruncated()) {
                    _plannedAnswer = plannedAnswer;
                }
                this.startResponder(plannedAnswer, port);
            }

        } finally {
            this.ioUnlock();
        }

        final long now = System.currentTimeMillis();
        for (DNSRecord answer : in.getAnswers()) {
            this.handleRecord(answer, now);
        }

        if (conflictDetected) {
            this.startProber();
        }
    }

    public void respondToQuery(DNSIncoming in) {
        this.ioLock();
        try {
            if (_plannedAnswer == in) {
                _plannedAnswer = null;
            }
        } finally {
            this.ioUnlock();
        }
    }

    /**
     * Add an answer to a question. Deal with the case when the outgoing packet overflows
     *
     * @param in
     * @param addr
     * @param port
     * @param out
     * @param rec
     * @return outgoing answer
     * @exception IOException
     */
    public DNSOutgoing addAnswer(DNSIncoming in, InetAddress addr, int port, DNSOutgoing out, DNSRecord rec) throws IOException {
        DNSOutgoing newOut = out;
        if (newOut == null) {
            newOut = new DNSOutgoing(DNSConstants.FLAGS_QR_RESPONSE | DNSConstants.FLAGS_AA, false, in.getSenderUDPPayload());
        }
        try {
            newOut.addAnswer(in, rec);
        } catch (final IOException e) {
            newOut.setFlags(newOut.getFlags() | DNSConstants.FLAGS_TC);
            newOut.setId(in.getId());
            send(newOut);

            newOut = new DNSOutgoing(DNSConstants.FLAGS_QR_RESPONSE | DNSConstants.FLAGS_AA, false, in.getSenderUDPPayload());
            newOut.addAnswer(in, rec);
        }
        return newOut;
    }

    /**
     * Send an outgoing multicast DNS message.
     *
     * @param out
     * @exception IOException
     */
    public void send(DNSOutgoing out) throws IOException {
        if (!out.isEmpty()) {
            byte[] message = out.data();
            final DatagramPacket packet = new DatagramPacket(message, message.length, _group, DNSConstants.MDNS_PORT);

            if (logger.isLoggable(Level.FINEST)) {
                try {
                    final DNSIncoming msg = new DNSIncoming(packet);
                    if (logger.isLoggable(Level.FINEST)) {
                        logger.finest("send(" + this.getName() + ") JmDNS out:" + msg.print(true));
                    }
                } catch (final IOException e) {
                    logger.throwing(getClass().toString(), "send(" + this.getName() + ") - JmDNS can not parse what it sends!!!", e);
                }
            }
            final MulticastSocket ms = _socket;
            if (ms != null && !ms.isClosed()) {
                ms.send(packet);
            }
        }
    }

    /*
     * (non-Javadoc)
     * @see javax.jmdns.impl.DNSTaskStarter#purgeTimer()
     */
    @Override
    public void purgeTimer() {
        DNSTaskStarter.Factory.getInstance().getStarter(this.getDns()).purgeTimer();
    }

    /*
     * (non-Javadoc)
     * @see javax.jmdns.impl.DNSTaskStarter#purgeStateTimer()
     */
    @Override
    public void purgeStateTimer() {
        DNSTaskStarter.Factory.getInstance().getStarter(this.getDns()).purgeStateTimer();
    }

    /*
     * (non-Javadoc)
     * @see javax.jmdns.impl.DNSTaskStarter#cancelTimer()
     */
    @Override
    public void cancelTimer() {
        DNSTaskStarter.Factory.getInstance().getStarter(this.getDns()).cancelTimer();
    }

    /*
     * (non-Javadoc)
     * @see javax.jmdns.impl.DNSTaskStarter#cancelStateTimer()
     */
    @Override
    public void cancelStateTimer() {
        DNSTaskStarter.Factory.getInstance().getStarter(this.getDns()).cancelStateTimer();
    }

    /*
     * (non-Javadoc)
     * @see javax.jmdns.impl.DNSTaskStarter#startProber()
     */
    @Override
    public void startProber() {
        DNSTaskStarter.Factory.getInstance().getStarter(this.getDns()).startProber();
    }

    /*
     * (non-Javadoc)
     * @see javax.jmdns.impl.DNSTaskStarter#startAnnouncer()
     */
    @Override
    public void startAnnouncer() {
        DNSTaskStarter.Factory.getInstance().getStarter(this.getDns()).startAnnouncer();
    }

    /*
     * (non-Javadoc)
     * @see javax.jmdns.impl.DNSTaskStarter#startRenewer()
     */
    @Override
    public void startRenewer() {
        DNSTaskStarter.Factory.getInstance().getStarter(this.getDns()).startRenewer();
    }

    /*
     * (non-Javadoc)
     * @see javax.jmdns.impl.DNSTaskStarter#startCanceler()
     */
    @Override
    public void startCanceler() {
        DNSTaskStarter.Factory.getInstance().getStarter(this.getDns()).startCanceler();
    }

    /*
     * (non-Javadoc)
     * @see javax.jmdns.impl.DNSTaskStarter#startReaper()
     */
    @Override
    public void startReaper() {
        DNSTaskStarter.Factory.getInstance().getStarter(this.getDns()).startReaper();
    }

    /*
     * (non-Javadoc)
     * @see javax.jmdns.impl.DNSTaskStarter#startServiceInfoResolver(javax.jmdns.impl.ServiceInfoImpl)
     */
    @Override
    public void startServiceInfoResolver(ServiceInfoImpl info) {
        DNSTaskStarter.Factory.getInstance().getStarter(this.getDns()).startServiceInfoResolver(info);
    }

    /*
     * (non-Javadoc)
     * @see javax.jmdns.impl.DNSTaskStarter#startTypeResolver()
     */
    @Override
    public void startTypeResolver() {
        DNSTaskStarter.Factory.getInstance().getStarter(this.getDns()).startTypeResolver();
    }

    /*
     * (non-Javadoc)
     * @see javax.jmdns.impl.DNSTaskStarter#startServiceResolver(java.lang.String)
     */
    @Override
    public void startServiceResolver(String type) {
        DNSTaskStarter.Factory.getInstance().getStarter(this.getDns()).startServiceResolver(type);
    }

    /*
     * (non-Javadoc)
     * @see javax.jmdns.impl.DNSTaskStarter#startResponder(javax.jmdns.impl.DNSIncoming, int)
     */
    @Override
    public void startResponder(DNSIncoming in, int port) {
        DNSTaskStarter.Factory.getInstance().getStarter(this.getDns()).startResponder(in, port);
    }

    // REMIND: Why is this not an anonymous inner class?
    /**
     * Shutdown operations.
     */
    protected class Shutdown implements Runnable {
        /** {@inheritDoc} */
        @Override
        public void run() {
            try {
                _shutdown = null;
                close();
            } catch (Throwable exception) {
                System.err.println("Error while shuting down. " + exception);
            }
        }
    }

    private final Object _recoverLock = new Object();

    /**
     * Recover jmdns when there is an error.
     */
    public void recover() {
        logger.finer(this.getName() + "recover()");
        // We have an IO error so lets try to recover if anything happens lets close it.
        // This should cover the case of the IP address changing under our feet
        if (this.isClosing() || this.isClosed() || this.isCanceling() || this.isCanceled()) {
            return;
        }

        // We need some definite lock here as we may have multiple timer running in the same thread that will not be stopped by the reentrant lock
        // in the state object. This is only a problem in this case as we are going to execute in seperate thread so that the timer can clear.
        synchronized (_recoverLock) {
            // Stop JmDNS
            // This protects against recursive calls
            if (this.cancelState()) {
                logger.finer(this.getName() + "recover() thread " + Thread.currentThread().getName());
                Thread recover = new Thread(this.getName() + ".recover()") {
                    /**
                     * {@inheritDoc}
                     */
                    @Override
                    public void run() {
                        __recover();
                    }
                };
                recover.start();
            }
        }
    }

    void __recover() {
        // Synchronize only if we are not already in process to prevent dead locks
        //
        if (logger.isLoggable(Level.FINER)) {
            logger.finer(this.getName() + "recover() Cleanning up");
        }

        logger.warning("RECOVERING");
        // Purge the timer
        this.purgeTimer();

        // We need to keep a copy for reregistration
        final Collection<ServiceInfo> oldServiceInfos = new ArrayList<ServiceInfo>(getServices().values());

        // Cancel all services
        this.unregisterAllServices();
        this.disposeServiceCollectors();

        this.waitForCanceled(DNSConstants.CLOSE_TIMEOUT);

        // Purge the canceler timer
        this.purgeStateTimer();

        //
        // close multicast socket
        this.closeMulticastSocket();

        //
        this.getCache().clear();
        if (logger.isLoggable(Level.FINER)) {
            logger.finer(this.getName() + "recover() All is clean");
        }

        if (this.isCanceled()) {
            //
            // All is clear now start the services
            //
            for (ServiceInfo info : oldServiceInfos) {
                ((ServiceInfoImpl) info).recoverState();
            }
            this.recoverState();

            try {
                this.openMulticastSocket(this.getLocalHost());
                this.start(oldServiceInfos);
            } catch (final Exception exception) {
                logger.log(Level.WARNING, this.getName() + "recover() Start services exception ", exception);
            }
            logger.log(Level.WARNING, this.getName() + "recover() We are back!");
        } else {
            // We have a problem. We could not clear the state.
            logger.log(Level.WARNING, this.getName() + "recover() Could not recover we are Down!");
            if (this.getDelegate() != null) {
                this.getDelegate().cannotRecoverFromIOError(this.getDns(), oldServiceInfos);
            }
        }

    }

    public void cleanCache() {
        long now = System.currentTimeMillis();
        for (DNSEntry entry : this.getCache().allValues()) {
            try {
                DNSRecord record = (DNSRecord) entry;
                if (record.isExpired(now)) {
                    this.updateRecord(now, record, Operation.Remove);
                    this.getCache().removeDNSEntry(record);
                } else if (record.isStale(now)) {
                    // we should query for the record we care about i.e. those in the service collectors
                    this.renewServiceCollector(record);
                }
            } catch (Exception exception) {
                logger.log(Level.SEVERE, this.getName() + ".Error while reaping records: " + entry, exception);
                logger.severe(this.toString());
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void close() {
        if (this.isClosing()) {
            return;
        }

        if (logger.isLoggable(Level.FINER)) {
            logger.finer("Cancelling JmDNS: " + this);
        }
        // Stop JmDNS
        // This protects against recursive calls
        if (this.closeState()) {
            // We got the tie break now clean up

            // Stop the timer
            logger.finer("Canceling the timer");
            this.cancelTimer();

            // Cancel all services
            this.unregisterAllServices();
            this.disposeServiceCollectors();

            if (logger.isLoggable(Level.FINER)) {
                logger.finer("Wait for JmDNS cancel: " + this);
            }
            this.waitForCanceled(DNSConstants.CLOSE_TIMEOUT);

            // Stop the canceler timer
            logger.finer("Canceling the state timer");
            this.cancelStateTimer();

            // Stop the executor
            _executor.shutdown();

            // close socket
            this.closeMulticastSocket();

            // remove the shutdown hook
            if (_shutdown != null) {
                Runtime.getRuntime().removeShutdownHook(_shutdown);
            }

            if (logger.isLoggable(Level.FINER)) {
                logger.finer("JmDNS closed.");
            }
        }
        advanceState(null);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @Deprecated
    public void printServices() {
        System.err.println(toString());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString() {
        final StringBuilder aLog = new StringBuilder(2048);
        aLog.append("\t---- Local Host -----");
        aLog.append("\n\t");
        aLog.append(_localHost);
        aLog.append("\n\t---- Services -----");
        for (String key : _services.keySet()) {
            aLog.append("\n\t\tService: ");
            aLog.append(key);
            aLog.append(": ");
            aLog.append(_services.get(key));
        }
        aLog.append("\n");
        aLog.append("\t---- Types ----");
        for (String key : _serviceTypes.keySet()) {
            ServiceTypeEntry subtypes = _serviceTypes.get(key);
            aLog.append("\n\t\tType: ");
            aLog.append(subtypes.getType());
            aLog.append(": ");
            aLog.append(subtypes.isEmpty() ? "no subtypes" : subtypes);
        }
        aLog.append("\n");
        aLog.append(_cache.toString());
        aLog.append("\n");
        aLog.append("\t---- Service Collectors ----");
        for (String key : _serviceCollectors.keySet()) {
            aLog.append("\n\t\tService Collector: ");
            aLog.append(key);
            aLog.append(": ");
            aLog.append(_serviceCollectors.get(key));
        }
        aLog.append("\n");
        aLog.append("\t---- Service Listeners ----");
        for (String key : _serviceListeners.keySet()) {
            aLog.append("\n\t\tService Listener: ");
            aLog.append(key);
            aLog.append(": ");
            aLog.append(_serviceListeners.get(key));
        }
        return aLog.toString();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ServiceInfo[] list(String type) {
        return this.list(type, DNSConstants.SERVICE_INFO_TIMEOUT);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ServiceInfo[] list(String type, long timeout) {
        this.cleanCache();
        // Implementation note: The first time a list for a given type is
        // requested, a ServiceCollector is created which collects service
        // infos. This greatly speeds up the performance of subsequent calls
        // to this method. The caveats are, that 1) the first call to this
        // method for a given type is slow, and 2) we spawn a ServiceCollector
        // instance for each service type which increases network traffic a
        // little.

        String loType = type.toLowerCase();

        boolean newCollectorCreated = false;
        if (this.isCanceling() || this.isCanceled()) {
            return new ServiceInfo[0];
        }

        ServiceCollector collector = _serviceCollectors.get(loType);
        if (collector == null) {
            newCollectorCreated = _serviceCollectors.putIfAbsent(loType, new ServiceCollector(type)) == null;
            collector = _serviceCollectors.get(loType);
            if (newCollectorCreated) {
                this.addServiceListener(type, collector, ListenerStatus.SYNCHONEOUS);
            }
        }
        if (logger.isLoggable(Level.FINER)) {
            logger.finer(this.getName() + ".collector: " + collector);
        }
        // At this stage the collector should never be null but it keeps findbugs happy.
        return (collector != null ? collector.list(timeout) : new ServiceInfo[0]);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Map<String, ServiceInfo[]> listBySubtype(String type) {
        return this.listBySubtype(type, DNSConstants.SERVICE_INFO_TIMEOUT);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Map<String, ServiceInfo[]> listBySubtype(String type, long timeout) {
        Map<String, List<ServiceInfo>> map = new HashMap<String, List<ServiceInfo>>(5);
        for (ServiceInfo info : this.list(type, timeout)) {
            String subtype = info.getSubtype().toLowerCase();
            if (!map.containsKey(subtype)) {
                map.put(subtype, new ArrayList<ServiceInfo>(10));
            }
            map.get(subtype).add(info);
        }

        Map<String, ServiceInfo[]> result = new HashMap<String, ServiceInfo[]>(map.size());
        for (String subtype : map.keySet()) {
            List<ServiceInfo> infoForSubType = map.get(subtype);
            result.put(subtype, infoForSubType.toArray(new ServiceInfo[infoForSubType.size()]));
        }

        return result;
    }

    /**
     * This method disposes all ServiceCollector instances which have been created by calls to method <code>list(type)</code>.
     *
     * @see #list
     */
    private void disposeServiceCollectors() {
        if (logger.isLoggable(Level.FINER)) {
            logger.finer("disposeServiceCollectors()");
        }
        for (String type : _serviceCollectors.keySet()) {
            ServiceCollector collector = _serviceCollectors.get(type);
            if (collector != null) {
                this.removeServiceListener(type, collector);
                _serviceCollectors.remove(type, collector);
            }
        }
    }

    /**
     * Instances of ServiceCollector are used internally to speed up the performance of method <code>list(type)</code>.
     *
     * @see #list
     */
    private static class ServiceCollector implements ServiceListener {
        // private static Logger logger = Logger.getLogger(ServiceCollector.class.getName());

        /**
         * A set of collected service instance names.
         */
        private final ConcurrentMap<String, ServiceInfo>  _infos;

        /**
         * A set of collected service event waiting to be resolved.
         */
        private final ConcurrentMap<String, ServiceEvent> _events;

        /**
         * This is the type we are listening for (only used for debugging).
         */
        private final String                              _type;

        /**
         * This is used to force a wait on the first invocation of list.
         */
        private volatile boolean                          _needToWaitForInfos;

        public ServiceCollector(String type) {
            super();
            _infos = new ConcurrentHashMap<String, ServiceInfo>();
            _events = new ConcurrentHashMap<String, ServiceEvent>();
            _type = type;
            _needToWaitForInfos = true;
        }

        /**
         * A service has been added.
         *
         * @param event
         *            service event
         */
        @Override
        public void serviceAdded(ServiceEvent event) {
            synchronized (this) {
                ServiceInfo info = event.getInfo();
                if ((info != null) && (info.hasData())) {
                    _infos.put(event.getName(), info);
                } else {
                    String subtype = (info != null ? info.getSubtype() : "");
                    info = ((JmDNSImpl) event.getDNS()).resolveServiceInfo(event.getType(), event.getName(), subtype, true);
                    if (info != null) {
                        _infos.put(event.getName(), info);
                    } else {
                        _events.put(event.getName(), event);
                    }
                }
            }
        }

        /**
         * A service has been removed.
         *
         * @param event
         *            service event
         */
        @Override
        public void serviceRemoved(ServiceEvent event) {
            synchronized (this) {
                _infos.remove(event.getName());
                _events.remove(event.getName());
            }
        }

        /**
         * A service has been resolved. Its details are now available in the ServiceInfo record.
         *
         * @param event
         *            service event
         */
        @Override
        public void serviceResolved(ServiceEvent event) {
            synchronized (this) {
                _infos.put(event.getName(), event.getInfo());
                _events.remove(event.getName());
            }
        }

        /**
         * Returns an array of all service infos which have been collected by this ServiceCollector.
         *
         * @param timeout
         *            timeout if the info list is empty.
         * @return Service Info array
         */
        public ServiceInfo[] list(long timeout) {
            if (_infos.isEmpty() || !_events.isEmpty() || _needToWaitForInfos) {
                long loops = (timeout / 200L);
                if (loops < 1) {
                    loops = 1;
                }
                for (int i = 0; i < loops; i++) {
                    try {
                        Thread.sleep(200);
                    } catch (final InterruptedException e) {
                        /* Stub */
                    }
                    if (_events.isEmpty() && !_infos.isEmpty() && !_needToWaitForInfos) {
                        break;
                    }
                }
            }
            _needToWaitForInfos = false;
            return _infos.values().toArray(new ServiceInfo[_infos.size()]);
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public String toString() {
            final StringBuffer aLog = new StringBuffer();
            aLog.append("\n\tType: ");
            aLog.append(_type);
            if (_infos.isEmpty()) {
                aLog.append("\n\tNo services collected.");
            } else {
                aLog.append("\n\tServices");
                for (String key : _infos.keySet()) {
                    aLog.append("\n\t\tService: ");
                    aLog.append(key);
                    aLog.append(": ");
                    aLog.append(_infos.get(key));
                }
            }
            if (_events.isEmpty()) {
                aLog.append("\n\tNo event queued.");
            } else {
                aLog.append("\n\tEvents");
                for (String key : _events.keySet()) {
                    aLog.append("\n\t\tEvent: ");
                    aLog.append(key);
                    aLog.append(": ");
                    aLog.append(_events.get(key));
                }
            }
            return aLog.toString();
        }
    }

    static String toUnqualifiedName(String type, String qualifiedName) {
        String loType = type.toLowerCase();
        String loQualifiedName = qualifiedName.toLowerCase();
        if (loQualifiedName.endsWith(loType) && !(loQualifiedName.equals(loType))) {
            return qualifiedName.substring(0, qualifiedName.length() - type.length() - 1);
        }
        return qualifiedName;
    }

    public Map<String, ServiceInfo> getServices() {
        return _services;
    }

    public void setLastThrottleIncrement(long lastThrottleIncrement) {
        this._lastThrottleIncrement = lastThrottleIncrement;
    }

    public long getLastThrottleIncrement() {
        return _lastThrottleIncrement;
    }

    public void setThrottle(int throttle) {
        this._throttle = throttle;
    }

    public int getThrottle() {
        return _throttle;
    }

    public static Random getRandom() {
        return _random;
    }

    public void ioLock() {
        _ioLock.lock();
    }

    public void ioUnlock() {
        _ioLock.unlock();
    }

    public void setPlannedAnswer(DNSIncoming plannedAnswer) {
        this._plannedAnswer = plannedAnswer;
    }

    public DNSIncoming getPlannedAnswer() {
        return _plannedAnswer;
    }

    void setLocalHost(HostInfo localHost) {
        this._localHost = localHost;
    }

    public Map<String, ServiceTypeEntry> getServiceTypes() {
        return _serviceTypes;
    }

    public MulticastSocket getSocket() {
        return _socket;
    }

    public InetAddress getGroup() {
        return _group;
    }

    @Override
    public Delegate getDelegate() {
        return this._delegate;
    }

    @Override
    public Delegate setDelegate(Delegate delegate) {
        Delegate previous = this._delegate;
        this._delegate = delegate;
        return previous;
    }

}
