Package javax.jmdns.impl.tasks

Source Code of javax.jmdns.impl.tasks.Prober

//Copyright 2003-2005 Arthur van Hoff, Rick Blair
//Licensed under Apache License version 2.0
//Original license LGPL

package javax.jmdns.impl.tasks;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.jmdns.impl.DNSConstants;
import javax.jmdns.impl.DNSOutgoing;
import javax.jmdns.impl.DNSQuestion;
import javax.jmdns.impl.DNSRecord;
import javax.jmdns.impl.DNSState;
import javax.jmdns.impl.JmDNSImpl;
import javax.jmdns.impl.ServiceInfoImpl;

/**
* The Prober sends three consecutive probes for all service infos
* that needs probing as well as for the host name.
* The state of each service info of the host name is advanced, when a probe has
* been sent for it.
* When the prober has run three times, it launches an Announcer.
* <p/>
* If a conflict during probes occurs, the affected service infos (and affected
* host name) are taken away from the prober. This eventually causes the prober
* tho cancel itself.
*/
public class Prober extends TimerTask
{
    static Logger logger = Logger.getLogger(Prober.class.getName());

    /**
     *
     */
    private final JmDNSImpl jmDNSImpl;
    /**
     * The state of the prober.
     */
    DNSState taskState = DNSState.PROBING_1;

    public Prober(JmDNSImpl jmDNSImpl)
    {
        this.jmDNSImpl = jmDNSImpl;
        // Associate the host name to this, if it needs probing
        if (this.jmDNSImpl.getState() == DNSState.PROBING_1)
        {
            this.jmDNSImpl.setTask(this);
        }
        // Associate services to this, if they need probing
        synchronized (this.jmDNSImpl)
        {
            for (Iterator iterator = this.jmDNSImpl.getServices().values().iterator(); iterator.hasNext();)
            {
                ServiceInfoImpl info = (ServiceInfoImpl) iterator.next();
                if (info.getState() == DNSState.PROBING_1)
                {
                    info.setTask(this);
                }
            }
        }
    }


    public void start(Timer timer)
    {
        long now = System.currentTimeMillis();
        if (now - this.jmDNSImpl.getLastThrottleIncrement() < DNSConstants.PROBE_THROTTLE_COUNT_INTERVAL)
        {
            this.jmDNSImpl.setThrottle(this.jmDNSImpl.getThrottle() + 1);
        }
        else
        {
            this.jmDNSImpl.setThrottle(1);
        }
        this.jmDNSImpl.setLastThrottleIncrement(now);

        if (this.jmDNSImpl.getState() == DNSState.ANNOUNCED && this.jmDNSImpl.getThrottle() < DNSConstants.PROBE_THROTTLE_COUNT)
        {
            timer.schedule(this, JmDNSImpl.getRandom().nextInt(1 + DNSConstants.PROBE_WAIT_INTERVAL), DNSConstants.PROBE_WAIT_INTERVAL);
        }
        else
        {
            timer.schedule(this, DNSConstants.PROBE_CONFLICT_INTERVAL, DNSConstants.PROBE_CONFLICT_INTERVAL);
        }
    }

    public boolean cancel()
    {
        // Remove association from host name to this
        if (this.jmDNSImpl.getTask() == this)
        {
            this.jmDNSImpl.setTask(null);
        }

        // Remove associations from services to this
        synchronized (this.jmDNSImpl)
        {
            for (Iterator i = this.jmDNSImpl.getServices().values().iterator(); i.hasNext();)
            {
                ServiceInfoImpl info = (ServiceInfoImpl) i.next();
                if (info.getTask() == this)
                {
                    info.setTask(null);
                }
            }
        }

        return super.cancel();
    }

    public void run()
    {
        synchronized (this.jmDNSImpl.getIoLock())
        {
            DNSOutgoing out = null;
            try
            {
                // send probes for JmDNS itself
                if (this.jmDNSImpl.getState() == taskState && this.jmDNSImpl.getTask() == this)
                {
                    if (out == null)
                    {
                        out = new DNSOutgoing(DNSConstants.FLAGS_QR_QUERY);
                    }
                    out.addQuestion(new DNSQuestion(this.jmDNSImpl.getLocalHost().getName(), DNSConstants.TYPE_ANY, DNSConstants.CLASS_IN));

                    this.jmDNSImpl.getLocalHost().addAddressRecords(out, true);
                    this.jmDNSImpl.advanceState();
                }
                // send probes 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 LinkedList(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.fine("run() JmDNS probing " + info.getQualifiedName() + " state " + info.getState());
                            if (out == null)
                            {
                                out = new DNSOutgoing(DNSConstants.FLAGS_QR_QUERY);
                                out.addQuestion(new DNSQuestion(info.getQualifiedName(), DNSConstants.TYPE_ANY, DNSConstants.CLASS_IN));
                            }
                            // the "unique" flag should be not set here because these answers haven't been proven unique yet
                            // this means the record will not exactly match the announcement record
                            out.addAuthorativeAnswer(new DNSRecord.Service(info.getQualifiedName(),
                                    DNSConstants.TYPE_SRV, DNSConstants.CLASS_IN, DNSConstants.DNS_TTL,
                                    info.getPriority(), info.getWeight(), info.getPort(), this.jmDNSImpl.getLocalHost().getName()));
                        }
                    }
                }
                if (out != null)
                {
                    logger.finer("run() JmDNS probing #" + taskState);
                    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();
                    return;
                }
            }
            catch (Throwable e)
            {
                logger.log(Level.WARNING, "run() exception ", e);
                this.jmDNSImpl.recover();
            }

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

                this.jmDNSImpl.startAnnouncer();
            }
        }
    }

}
TOP

Related Classes of javax.jmdns.impl.tasks.Prober

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.