13742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman// Copyright 2003-2005 Arthur van Hoff, Rick Blair 23742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman// Licensed under Apache License version 2.0 33742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman// Original license LGPL 43742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 53742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanpackage javax.jmdns.impl.tasks.state; 63742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 73742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport java.io.IOException; 83742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport java.util.Timer; 93742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport java.util.logging.Logger; 103742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 113742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport javax.jmdns.impl.DNSOutgoing; 123742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport javax.jmdns.impl.DNSQuestion; 133742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport javax.jmdns.impl.DNSRecord; 143742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport javax.jmdns.impl.JmDNSImpl; 153742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport javax.jmdns.impl.ServiceInfoImpl; 163742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport javax.jmdns.impl.constants.DNSConstants; 173742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport javax.jmdns.impl.constants.DNSRecordClass; 183742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport javax.jmdns.impl.constants.DNSRecordType; 193742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport javax.jmdns.impl.constants.DNSState; 203742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 213742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman/** 223742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * 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, 233742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * it launches an Announcer. 243742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * <p/> 253742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * 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. 263742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman */ 273742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanpublic class Prober extends DNSStateTask { 283742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman static Logger logger = Logger.getLogger(Prober.class.getName()); 293742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 303742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman public Prober(JmDNSImpl jmDNSImpl) { 313742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman super(jmDNSImpl, defaultTTL()); 323742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 333742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman this.setTaskState(DNSState.PROBING_1); 343742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman this.associate(DNSState.PROBING_1); 353742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 363742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 373742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman /* 383742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * (non-Javadoc) 393742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * @see javax.jmdns.impl.tasks.DNSTask#getName() 403742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman */ 413742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman @Override 423742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman public String getName() { 433742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman return "Prober(" + (this.getDns() != null ? this.getDns().getName() : "") + ")"; 443742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 453742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 463742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman /* 473742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * (non-Javadoc) 483742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * @see java.lang.Object#toString() 493742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman */ 503742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman @Override 513742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman public String toString() { 523742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman return super.toString() + " state: " + this.getTaskState(); 533742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 543742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 553742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman /* 563742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * (non-Javadoc) 573742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * @see javax.jmdns.impl.tasks.DNSTask#start(java.util.Timer) 583742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman */ 593742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman @Override 603742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman public void start(Timer timer) { 613742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman long now = System.currentTimeMillis(); 623742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (now - this.getDns().getLastThrottleIncrement() < DNSConstants.PROBE_THROTTLE_COUNT_INTERVAL) { 633742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman this.getDns().setThrottle(this.getDns().getThrottle() + 1); 643742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } else { 653742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman this.getDns().setThrottle(1); 663742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 673742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman this.getDns().setLastThrottleIncrement(now); 683742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 693742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (this.getDns().isAnnounced() && this.getDns().getThrottle() < DNSConstants.PROBE_THROTTLE_COUNT) { 703742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman timer.schedule(this, JmDNSImpl.getRandom().nextInt(1 + DNSConstants.PROBE_WAIT_INTERVAL), DNSConstants.PROBE_WAIT_INTERVAL); 713742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } else if (!this.getDns().isCanceling() && !this.getDns().isCanceled()) { 723742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman timer.schedule(this, DNSConstants.PROBE_CONFLICT_INTERVAL, DNSConstants.PROBE_CONFLICT_INTERVAL); 733742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 743742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 753742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 763742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman @Override 773742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman public boolean cancel() { 783742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman this.removeAssociation(); 793742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 803742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman return super.cancel(); 813742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 823742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 833742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman /* 843742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * (non-Javadoc) 853742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * @see javax.jmdns.impl.tasks.state.DNSStateTask#getTaskDescription() 863742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman */ 873742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman @Override 883742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman public String getTaskDescription() { 893742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman return "probing"; 903742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 913742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 923742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman /* 933742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * (non-Javadoc) 943742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * @see javax.jmdns.impl.tasks.state.DNSStateTask#checkRunCondition() 953742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman */ 963742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman @Override 973742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman protected boolean checkRunCondition() { 983742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman return !this.getDns().isCanceling() && !this.getDns().isCanceled(); 993742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 1003742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 1013742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman /* 1023742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * (non-Javadoc) 1033742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * @see javax.jmdns.impl.tasks.state.DNSStateTask#createOugoing() 1043742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman */ 1053742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman @Override 1063742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman protected DNSOutgoing createOugoing() { 1073742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman return new DNSOutgoing(DNSConstants.FLAGS_QR_QUERY); 1083742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 1093742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 1103742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman /* 1113742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * (non-Javadoc) 1123742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * @see javax.jmdns.impl.tasks.state.DNSStateTask#buildOutgoingForDNS(javax.jmdns.impl.DNSOutgoing) 1133742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman */ 1143742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman @Override 1153742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman protected DNSOutgoing buildOutgoingForDNS(DNSOutgoing out) throws IOException { 1163742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman DNSOutgoing newOut = out; 1173742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman newOut.addQuestion(DNSQuestion.newQuestion(this.getDns().getLocalHost().getName(), DNSRecordType.TYPE_ANY, DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE)); 1183742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman for (DNSRecord answer : this.getDns().getLocalHost().answers(DNSRecordClass.NOT_UNIQUE, this.getTTL())) { 1193742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman newOut = this.addAuthoritativeAnswer(newOut, answer); 1203742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 1213742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman return newOut; 1223742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 1233742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 1243742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman /* 1253742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * (non-Javadoc) 1263742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * @see javax.jmdns.impl.tasks.state.DNSStateTask#buildOutgoingForInfo(javax.jmdns.impl.ServiceInfoImpl, javax.jmdns.impl.DNSOutgoing) 1273742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman */ 1283742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman @Override 1293742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman protected DNSOutgoing buildOutgoingForInfo(ServiceInfoImpl info, DNSOutgoing out) throws IOException { 1303742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman DNSOutgoing newOut = out; 1313742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman newOut = this.addQuestion(newOut, DNSQuestion.newQuestion(info.getQualifiedName(), DNSRecordType.TYPE_ANY, DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE)); 1323742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman // 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 1333742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 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() 1343742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman .getName())); 1353742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman return newOut; 1363742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 1373742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 1383742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman /* 1393742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * (non-Javadoc) 1403742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * @see javax.jmdns.impl.tasks.state.DNSStateTask#recoverTask(java.lang.Throwable) 1413742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman */ 1423742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman @Override 1433742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman protected void recoverTask(Throwable e) { 1443742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman this.getDns().recover(); 1453742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 1463742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 1473742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman /* 1483742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * (non-Javadoc) 1493742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * @see javax.jmdns.impl.tasks.state.DNSStateTask#advanceTask() 1503742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman */ 1513742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman @Override 1523742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman protected void advanceTask() { 1533742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman this.setTaskState(this.getTaskState().advance()); 1543742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (!this.getTaskState().isProbing()) { 1553742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman cancel(); 1563742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 1573742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman this.getDns().startAnnouncer(); 1583742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 1593742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 1603742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 1613742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman}