public void run()
    {
        DNSOutgoing out = null;
        try
        {
            // send probes for JmDNS itself
            if (this.jmDNSImpl.getState() == taskState)
            {
                if (out == null)
                {
                    out = new DNSOutgoing(DNSConstants.FLAGS_QR_RESPONSE | DNSConstants.FLAGS_AA);
                }
                this.jmDNSImpl.getLocalHost().addAddressRecords(out, false);
                this.jmDNSImpl.advanceState();
            }
            // send announces for services
            // Defensively copy the services into a local list,
            // to prevent race conditions with methods registerService
            // and unregisterService.
            List list;
            synchronized (this.jmDNSImpl)
            {
                list = new ArrayList(this.jmDNSImpl.getServices().values());
            }
            for (Iterator i = list.iterator(); i.hasNext();)
            {
                ServiceInfoImpl info = (ServiceInfoImpl) i.next();
                synchronized (info)
                {
                    if (info.getState() == taskState && info.getTask() == this)
                    {
                        info.advanceState();
                        logger.finer("run() JmDNS announced " + info.getQualifiedName() + " state " + info.getState());
                        if (out == null)
                        {
                            out = new DNSOutgoing(DNSConstants.FLAGS_QR_RESPONSE | DNSConstants.FLAGS_AA);
                        }
                        info.addAnswers(out, DNSConstants.DNS_TTL, this.jmDNSImpl.getLocalHost());
                    }
                }
            }
            if (out != null)
            {
                logger.finer("run() JmDNS announced");
                this.jmDNSImpl.send(out);
            }
            else
            {
                // If we have nothing to send, another timer taskState ahead
                // of us has done the job for us. We can cancel.
                cancel();
            }
        }
        catch (Throwable e)
        {
            logger.log(Level.WARNING, "run() exception ", e);
            this.jmDNSImpl.recover();
        }

        taskState = taskState.advance();
        if (!taskState.isAnnounced())
        {
            cancel();

        }
    }