View Javadoc

1   // Copyright 2003-2005 Arthur van Hoff, Rick Blair
2   // Licensed under Apache License version 2.0
3   // Original license LGPL
4   
5   package javax.jmdns.impl.tasks.state;
6   
7   import java.io.IOException;
8   import java.util.Timer;
9   import java.util.logging.Logger;
10  
11  import javax.jmdns.impl.DNSOutgoing;
12  import javax.jmdns.impl.DNSQuestion;
13  import javax.jmdns.impl.DNSRecord;
14  import javax.jmdns.impl.JmDNSImpl;
15  import javax.jmdns.impl.ServiceInfoImpl;
16  import javax.jmdns.impl.constants.DNSConstants;
17  import javax.jmdns.impl.constants.DNSRecordClass;
18  import javax.jmdns.impl.constants.DNSRecordType;
19  import javax.jmdns.impl.constants.DNSState;
20  
21  /**
22   * 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,
23   * it launches an Announcer.
24   * <p/>
25   * 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 to cancel itself.
26   */
27  public class Prober extends DNSStateTask {
28      static Logger logger = Logger.getLogger(Prober.class.getName());
29  
30      public Prober(JmDNSImpl jmDNSImpl) {
31          super(jmDNSImpl, defaultTTL());
32  
33          this.setTaskState(DNSState.PROBING_1);
34          this.associate(DNSState.PROBING_1);
35      }
36  
37      /*
38       * (non-Javadoc)
39       * @see javax.jmdns.impl.tasks.DNSTask#getName()
40       */
41      @Override
42      public String getName() {
43          return "Prober(" + (this.getDns() != null ? this.getDns().getName() : "") + ")";
44      }
45  
46      /*
47       * (non-Javadoc)
48       * @see java.lang.Object#toString()
49       */
50      @Override
51      public String toString() {
52          return super.toString() + " state: " + this.getTaskState();
53      }
54  
55      /*
56       * (non-Javadoc)
57       * @see javax.jmdns.impl.tasks.DNSTask#start(java.util.Timer)
58       */
59      @Override
60      public void start(Timer timer) {
61          long now = System.currentTimeMillis();
62          if (now - this.getDns().getLastThrottleIncrement() < DNSConstants.PROBE_THROTTLE_COUNT_INTERVAL) {
63              this.getDns().setThrottle(this.getDns().getThrottle() + 1);
64          } else {
65              this.getDns().setThrottle(1);
66          }
67          this.getDns().setLastThrottleIncrement(now);
68  
69          if (this.getDns().isAnnounced() && this.getDns().getThrottle() < DNSConstants.PROBE_THROTTLE_COUNT) {
70              timer.schedule(this, JmDNSImpl.getRandom().nextInt(1 + DNSConstants.PROBE_WAIT_INTERVAL), DNSConstants.PROBE_WAIT_INTERVAL);
71          } else if (!this.getDns().isCanceling() && !this.getDns().isCanceled()) {
72              timer.schedule(this, DNSConstants.PROBE_CONFLICT_INTERVAL, DNSConstants.PROBE_CONFLICT_INTERVAL);
73          }
74      }
75  
76      @Override
77      public boolean cancel() {
78          this.removeAssociation();
79  
80          return super.cancel();
81      }
82  
83      /*
84       * (non-Javadoc)
85       * @see javax.jmdns.impl.tasks.state.DNSStateTask#getTaskDescription()
86       */
87      @Override
88      public String getTaskDescription() {
89          return "probing";
90      }
91  
92      /*
93       * (non-Javadoc)
94       * @see javax.jmdns.impl.tasks.state.DNSStateTask#checkRunCondition()
95       */
96      @Override
97      protected boolean checkRunCondition() {
98          return !this.getDns().isCanceling() && !this.getDns().isCanceled();
99      }
100 
101     /*
102      * (non-Javadoc)
103      * @see javax.jmdns.impl.tasks.state.DNSStateTask#createOugoing()
104      */
105     @Override
106     protected DNSOutgoing createOugoing() {
107         return new DNSOutgoing(DNSConstants.FLAGS_QR_QUERY);
108     }
109 
110     /*
111      * (non-Javadoc)
112      * @see javax.jmdns.impl.tasks.state.DNSStateTask#buildOutgoingForDNS(javax.jmdns.impl.DNSOutgoing)
113      */
114     @Override
115     protected DNSOutgoing buildOutgoingForDNS(DNSOutgoing out) throws IOException {
116         DNSOutgoing newOut = out;
117         newOut.addQuestion(DNSQuestion.newQuestion(this.getDns().getLocalHost().getName(), DNSRecordType.TYPE_ANY, DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE));
118         for (DNSRecord answer : this.getDns().getLocalHost().answers(DNSRecordClass.NOT_UNIQUE, this.getTTL())) {
119             newOut = this.addAuthoritativeAnswer(newOut, answer);
120         }
121         return newOut;
122     }
123 
124     /*
125      * (non-Javadoc)
126      * @see javax.jmdns.impl.tasks.state.DNSStateTask#buildOutgoingForInfo(javax.jmdns.impl.ServiceInfoImpl, javax.jmdns.impl.DNSOutgoing)
127      */
128     @Override
129     protected DNSOutgoing buildOutgoingForInfo(ServiceInfoImpl info, DNSOutgoing out) throws IOException {
130         DNSOutgoing newOut = out;
131         newOut = this.addQuestion(newOut, DNSQuestion.newQuestion(info.getQualifiedName(), DNSRecordType.TYPE_ANY, DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE));
132         // 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
133         newOut = this.addAuthoritativeAnswer(newOut, new DNSRecord.Service(info.getQualifiedName(), DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE, this.getTTL(), info.getPriority(), info.getWeight(), info.getPort(), this.getDns().getLocalHost()
134                 .getName()));
135         return newOut;
136     }
137 
138     /*
139      * (non-Javadoc)
140      * @see javax.jmdns.impl.tasks.state.DNSStateTask#recoverTask(java.lang.Throwable)
141      */
142     @Override
143     protected void recoverTask(Throwable e) {
144         this.getDns().recover();
145     }
146 
147     /*
148      * (non-Javadoc)
149      * @see javax.jmdns.impl.tasks.state.DNSStateTask#advanceTask()
150      */
151     @Override
152     protected void advanceTask() {
153         this.setTaskState(this.getTaskState().advance());
154         if (!this.getTaskState().isProbing()) {
155             cancel();
156 
157             this.getDns().startAnnouncer();
158         }
159     }
160 
161 }