1// Licensed under Apache License version 2.0
2package javax.jmdns.impl.tasks.resolver;
3
4import java.io.IOException;
5import java.util.Timer;
6import java.util.logging.Level;
7import java.util.logging.Logger;
8
9import javax.jmdns.impl.DNSOutgoing;
10import javax.jmdns.impl.JmDNSImpl;
11import javax.jmdns.impl.constants.DNSConstants;
12import javax.jmdns.impl.tasks.DNSTask;
13
14/**
15 * This is the root class for all resolver tasks.
16 *
17 * @author Pierre Frisch
18 */
19public abstract class DNSResolverTask extends DNSTask {
20    private static Logger logger = Logger.getLogger(DNSResolverTask.class.getName());
21
22    /**
23     * Counts the number of queries being sent.
24     */
25    protected int         _count = 0;
26
27    /**
28     * @param jmDNSImpl
29     */
30    public DNSResolverTask(JmDNSImpl jmDNSImpl) {
31        super(jmDNSImpl);
32    }
33
34    /*
35     * (non-Javadoc)
36     * @see java.lang.Object#toString()
37     */
38    @Override
39    public String toString() {
40        return super.toString() + " count: " + _count;
41    }
42
43    /*
44     * (non-Javadoc)
45     * @see javax.jmdns.impl.tasks.DNSTask#start(java.util.Timer)
46     */
47    @Override
48    public void start(Timer timer) {
49        if (!this.getDns().isCanceling() && !this.getDns().isCanceled()) {
50            timer.schedule(this, DNSConstants.QUERY_WAIT_INTERVAL, DNSConstants.QUERY_WAIT_INTERVAL);
51        }
52    }
53
54    /*
55     * (non-Javadoc)
56     * @see java.util.TimerTask#run()
57     */
58    @Override
59    public void run() {
60        try {
61            if (this.getDns().isCanceling() || this.getDns().isCanceled()) {
62                this.cancel();
63            } else {
64                if (_count++ < 3) {
65                    if (logger.isLoggable(Level.FINER)) {
66                        logger.finer(this.getName() + ".run() JmDNS " + this.description());
67                    }
68                    DNSOutgoing out = new DNSOutgoing(DNSConstants.FLAGS_QR_QUERY);
69                    out = this.addQuestions(out);
70                    if (this.getDns().isAnnounced()) {
71                        out = this.addAnswers(out);
72                    }
73                    if (!out.isEmpty()) {
74                        this.getDns().send(out);
75                    }
76                } else {
77                    // After three queries, we can quit.
78                    this.cancel();
79                }
80            }
81        } catch (Throwable e) {
82            logger.log(Level.WARNING, this.getName() + ".run() exception ", e);
83            this.getDns().recover();
84        }
85    }
86
87    /**
88     * Overridden by subclasses to add questions to the message.<br/>
89     * <b>Note:</b> Because of message size limitation the returned message may be different than the message parameter.
90     *
91     * @param out
92     *            outgoing message
93     * @return the outgoing message.
94     * @exception IOException
95     */
96    protected abstract DNSOutgoing addQuestions(DNSOutgoing out) throws IOException;
97
98    /**
99     * Overridden by subclasses to add questions to the message.<br/>
100     * <b>Note:</b> Because of message size limitation the returned message may be different than the message parameter.
101     *
102     * @param out
103     *            outgoing message
104     * @return the outgoing message.
105     * @exception IOException
106     */
107    protected abstract DNSOutgoing addAnswers(DNSOutgoing out) throws IOException;
108
109    /**
110     * Returns a description of the resolver for debugging
111     *
112     * @return resolver description
113     */
114    protected abstract String description();
115
116}
117