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 }