Responder.java
Go to the documentation of this file.
00001 // Copyright 2003-2005 Arthur van Hoff, Rick Blair
00002 // Licensed under Apache License version 2.0
00003 // Original license LGPL
00004 
00005 package javax.jmdns.impl.tasks;
00006 
00007 import java.util.HashSet;
00008 import java.util.Set;
00009 import java.util.Timer;
00010 import java.util.logging.Level;
00011 import java.util.logging.Logger;
00012 
00013 import javax.jmdns.impl.DNSIncoming;
00014 import javax.jmdns.impl.DNSOutgoing;
00015 import javax.jmdns.impl.DNSQuestion;
00016 import javax.jmdns.impl.DNSRecord;
00017 import javax.jmdns.impl.JmDNSImpl;
00018 import javax.jmdns.impl.constants.DNSConstants;
00019 
00023 public class Responder extends DNSTask {
00024     static Logger             logger = Logger.getLogger(Responder.class.getName());
00025 
00029     private final DNSIncoming _in;
00030 
00034     private final boolean     _unicast;
00035 
00036     public Responder(JmDNSImpl jmDNSImpl, DNSIncoming in, int port) {
00037         super(jmDNSImpl);
00038         this._in = in;
00039         this._unicast = (port != DNSConstants.MDNS_PORT);
00040     }
00041 
00042     /*
00043      * (non-Javadoc)
00044      * @see javax.jmdns.impl.tasks.DNSTask#getName()
00045      */
00046     @Override
00047     public String getName() {
00048         return "Responder(" + (this.getDns() != null ? this.getDns().getName() : "") + ")";
00049     }
00050 
00051     /*
00052      * (non-Javadoc)
00053      * @see java.lang.Object#toString()
00054      */
00055     @Override
00056     public String toString() {
00057         return super.toString() + " incomming: " + _in;
00058     }
00059 
00060     /*
00061      * (non-Javadoc)
00062      * @see javax.jmdns.impl.tasks.DNSTask#start(java.util.Timer)
00063      */
00064     @Override
00065     public void start(Timer timer) {
00066         // According to draft-cheshire-dnsext-multicastdns.txt chapter "7 Responding":
00067         // We respond immediately if we know for sure, that we are the only one who can respond to the query.
00068         // In all other cases, we respond within 20-120 ms.
00069         //
00070         // According to draft-cheshire-dnsext-multicastdns.txt chapter "6.2 Multi-Packet Known Answer Suppression":
00071         // We respond after 20-120 ms if the query is truncated.
00072 
00073         boolean iAmTheOnlyOne = true;
00074         for (DNSQuestion question : _in.getQuestions()) {
00075             if (logger.isLoggable(Level.FINEST)) {
00076                 logger.finest(this.getName() + "start() question=" + question);
00077             }
00078             iAmTheOnlyOne = question.iAmTheOnlyOne(this.getDns());
00079             if (!iAmTheOnlyOne) {
00080                 break;
00081             }
00082         }
00083         int delay = (iAmTheOnlyOne && !_in.isTruncated()) ? 0 : DNSConstants.RESPONSE_MIN_WAIT_INTERVAL + JmDNSImpl.getRandom().nextInt(DNSConstants.RESPONSE_MAX_WAIT_INTERVAL - DNSConstants.RESPONSE_MIN_WAIT_INTERVAL + 1) - _in.elapseSinceArrival();
00084         if (delay < 0) {
00085             delay = 0;
00086         }
00087         if (logger.isLoggable(Level.FINEST)) {
00088             logger.finest(this.getName() + "start() Responder chosen delay=" + delay);
00089         }
00090         if (!this.getDns().isCanceling() && !this.getDns().isCanceled()) {
00091             timer.schedule(this, delay);
00092         }
00093     }
00094 
00095     @Override
00096     public void run() {
00097         this.getDns().respondToQuery(_in);
00098 
00099         // We use these sets to prevent duplicate records
00100         Set<DNSQuestion> questions = new HashSet<DNSQuestion>();
00101         Set<DNSRecord> answers = new HashSet<DNSRecord>();
00102 
00103         if (this.getDns().isAnnounced()) {
00104             try {
00105                 // Answer questions
00106                 for (DNSQuestion question : _in.getQuestions()) {
00107                     if (logger.isLoggable(Level.FINER)) {
00108                         logger.finer(this.getName() + "run() JmDNS responding to: " + question);
00109                     }
00110                     // for unicast responses the question must be included
00111                     if (_unicast) {
00112                         // out.addQuestion(q);
00113                         questions.add(question);
00114                     }
00115 
00116                     question.addAnswers(this.getDns(), answers);
00117                 }
00118 
00119                 // remove known answers, if the ttl is at least half of the correct value. (See Draft Cheshire chapter 7.1.).
00120                 long now = System.currentTimeMillis();
00121                 for (DNSRecord knownAnswer : _in.getAnswers()) {
00122                     if (knownAnswer.isStale(now)) {
00123                         answers.remove(knownAnswer);
00124                         if (logger.isLoggable(Level.FINER)) {
00125                             logger.finer(this.getName() + "JmDNS Responder Known Answer Removed");
00126                         }
00127                     }
00128                 }
00129 
00130                 // respond if we have answers
00131                 if (!answers.isEmpty()) {
00132                     if (logger.isLoggable(Level.FINER)) {
00133                         logger.finer(this.getName() + "run() JmDNS responding");
00134                     }
00135                     DNSOutgoing out = new DNSOutgoing(DNSConstants.FLAGS_QR_RESPONSE | DNSConstants.FLAGS_AA, !_unicast, _in.getSenderUDPPayload());
00136                     out.setId(_in.getId());
00137                     for (DNSQuestion question : questions) {
00138                         if (question != null) {
00139                             out = this.addQuestion(out, question);
00140                         }
00141                     }
00142                     for (DNSRecord answer : answers) {
00143                         if (answer != null) {
00144                             out = this.addAnswer(out, _in, answer);
00145 
00146                         }
00147                     }
00148                     if (!out.isEmpty()) this.getDns().send(out);
00149                 }
00150                 // this.cancel();
00151             } catch (Throwable e) {
00152                 logger.log(Level.WARNING, this.getName() + "run() exception ", e);
00153                 this.getDns().close();
00154             }
00155         }
00156     }
00157 }


zeroconf_jmdns_suite
Author(s): Daniel Stonier
autogenerated on Thu Aug 27 2015 15:50:27