summaryrefslogtreecommitdiff
path: root/src/javax/jmdns/impl/tasks/state
diff options
context:
space:
mode:
Diffstat (limited to 'src/javax/jmdns/impl/tasks/state')
-rw-r--r--src/javax/jmdns/impl/tasks/state/Announcer.java146
-rw-r--r--src/javax/jmdns/impl/tasks/state/Canceler.java143
-rw-r--r--src/javax/jmdns/impl/tasks/state/DNSStateTask.java188
-rw-r--r--src/javax/jmdns/impl/tasks/state/Prober.java161
-rw-r--r--src/javax/jmdns/impl/tasks/state/Renewer.java144
-rw-r--r--src/javax/jmdns/impl/tasks/state/package-info.java2
6 files changed, 784 insertions, 0 deletions
diff --git a/src/javax/jmdns/impl/tasks/state/Announcer.java b/src/javax/jmdns/impl/tasks/state/Announcer.java
new file mode 100644
index 0000000..aff60f7
--- /dev/null
+++ b/src/javax/jmdns/impl/tasks/state/Announcer.java
@@ -0,0 +1,146 @@
+// Copyright 2003-2005 Arthur van Hoff, Rick Blair
+// Licensed under Apache License version 2.0
+// Original license LGPL
+
+package javax.jmdns.impl.tasks.state;
+
+import java.io.IOException;
+import java.util.Timer;
+import java.util.logging.Logger;
+
+import javax.jmdns.impl.DNSOutgoing;
+import javax.jmdns.impl.DNSRecord;
+import javax.jmdns.impl.JmDNSImpl;
+import javax.jmdns.impl.ServiceInfoImpl;
+import javax.jmdns.impl.constants.DNSConstants;
+import javax.jmdns.impl.constants.DNSRecordClass;
+import javax.jmdns.impl.constants.DNSState;
+
+/**
+ * The Announcer sends an accumulated query of all announces, and advances the state of all serviceInfos, for which it has sent an announce. The Announcer also sends announcements and advances the state of JmDNS itself.
+ * <p/>
+ * When the announcer has run two times, it finishes.
+ */
+public class Announcer extends DNSStateTask {
+ static Logger logger = Logger.getLogger(Announcer.class.getName());
+
+ public Announcer(JmDNSImpl jmDNSImpl) {
+ super(jmDNSImpl, defaultTTL());
+
+ this.setTaskState(DNSState.ANNOUNCING_1);
+ this.associate(DNSState.ANNOUNCING_1);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.DNSTask#getName()
+ */
+ @Override
+ public String getName() {
+ return "Announcer(" + (this.getDns() != null ? this.getDns().getName() : "") + ")";
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return super.toString() + " state: " + this.getTaskState();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.DNSTask#start(java.util.Timer)
+ */
+ @Override
+ public void start(Timer timer) {
+ if (!this.getDns().isCanceling() && !this.getDns().isCanceled()) {
+ timer.schedule(this, DNSConstants.ANNOUNCE_WAIT_INTERVAL, DNSConstants.ANNOUNCE_WAIT_INTERVAL);
+ }
+ }
+
+ @Override
+ public boolean cancel() {
+ this.removeAssociation();
+
+ return super.cancel();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.state.DNSStateTask#getTaskDescription()
+ */
+ @Override
+ public String getTaskDescription() {
+ return "announcing";
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.state.DNSStateTask#checkRunCondition()
+ */
+ @Override
+ protected boolean checkRunCondition() {
+ return !this.getDns().isCanceling() && !this.getDns().isCanceled();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.state.DNSStateTask#createOugoing()
+ */
+ @Override
+ protected DNSOutgoing createOugoing() {
+ return new DNSOutgoing(DNSConstants.FLAGS_QR_RESPONSE | DNSConstants.FLAGS_AA);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.state.DNSStateTask#buildOutgoingForDNS(javax.jmdns.impl.DNSOutgoing)
+ */
+ @Override
+ protected DNSOutgoing buildOutgoingForDNS(DNSOutgoing out) throws IOException {
+ DNSOutgoing newOut = out;
+ for (DNSRecord answer : this.getDns().getLocalHost().answers(DNSRecordClass.UNIQUE, this.getTTL())) {
+ newOut = this.addAnswer(newOut, null, answer);
+ }
+ return newOut;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.state.DNSStateTask#buildOutgoingForInfo(javax.jmdns.impl.ServiceInfoImpl, javax.jmdns.impl.DNSOutgoing)
+ */
+ @Override
+ protected DNSOutgoing buildOutgoingForInfo(ServiceInfoImpl info, DNSOutgoing out) throws IOException {
+ DNSOutgoing newOut = out;
+ for (DNSRecord answer : info.answers(DNSRecordClass.UNIQUE, this.getTTL(), this.getDns().getLocalHost())) {
+ newOut = this.addAnswer(newOut, null, answer);
+ }
+ return newOut;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.state.DNSStateTask#recoverTask(java.lang.Throwable)
+ */
+ @Override
+ protected void recoverTask(Throwable e) {
+ this.getDns().recover();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.state.DNSStateTask#advanceTask()
+ */
+ @Override
+ protected void advanceTask() {
+ this.setTaskState(this.getTaskState().advance());
+ if (!this.getTaskState().isAnnouncing()) {
+ this.cancel();
+
+ this.getDns().startRenewer();
+ }
+ }
+
+} \ No newline at end of file
diff --git a/src/javax/jmdns/impl/tasks/state/Canceler.java b/src/javax/jmdns/impl/tasks/state/Canceler.java
new file mode 100644
index 0000000..50cf316
--- /dev/null
+++ b/src/javax/jmdns/impl/tasks/state/Canceler.java
@@ -0,0 +1,143 @@
+// Copyright 2003-2005 Arthur van Hoff, Rick Blair
+// Licensed under Apache License version 2.0
+// Original license LGPL
+
+package javax.jmdns.impl.tasks.state;
+
+import java.io.IOException;
+import java.util.Timer;
+import java.util.logging.Logger;
+
+import javax.jmdns.impl.DNSOutgoing;
+import javax.jmdns.impl.DNSRecord;
+import javax.jmdns.impl.JmDNSImpl;
+import javax.jmdns.impl.ServiceInfoImpl;
+import javax.jmdns.impl.constants.DNSConstants;
+import javax.jmdns.impl.constants.DNSRecordClass;
+import javax.jmdns.impl.constants.DNSState;
+
+/**
+ * The Canceler sends two announces with TTL=0 for the specified services.
+ */
+public class Canceler extends DNSStateTask {
+ static Logger logger = Logger.getLogger(Canceler.class.getName());
+
+ public Canceler(JmDNSImpl jmDNSImpl) {
+ super(jmDNSImpl, 0);
+
+ this.setTaskState(DNSState.CANCELING_1);
+ this.associate(DNSState.CANCELING_1);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.DNSTask#getName()
+ */
+ @Override
+ public String getName() {
+ return "Canceler(" + (this.getDns() != null ? this.getDns().getName() : "") + ")";
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return super.toString() + " state: " + this.getTaskState();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.DNSTask#start(java.util.Timer)
+ */
+ @Override
+ public void start(Timer timer) {
+ timer.schedule(this, 0, DNSConstants.ANNOUNCE_WAIT_INTERVAL);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.util.TimerTask#cancel()
+ */
+ @Override
+ public boolean cancel() {
+ this.removeAssociation();
+
+ return super.cancel();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.state.DNSStateTask#getTaskDescription()
+ */
+ @Override
+ public String getTaskDescription() {
+ return "canceling";
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.state.DNSStateTask#checkRunCondition()
+ */
+ @Override
+ protected boolean checkRunCondition() {
+ return true;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.state.DNSStateTask#createOugoing()
+ */
+ @Override
+ protected DNSOutgoing createOugoing() {
+ return new DNSOutgoing(DNSConstants.FLAGS_QR_RESPONSE | DNSConstants.FLAGS_AA);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.state.DNSStateTask#buildOutgoingForDNS(javax.jmdns.impl.DNSOutgoing)
+ */
+ @Override
+ protected DNSOutgoing buildOutgoingForDNS(DNSOutgoing out) throws IOException {
+ DNSOutgoing newOut = out;
+ for (DNSRecord answer : this.getDns().getLocalHost().answers(DNSRecordClass.UNIQUE, this.getTTL())) {
+ newOut = this.addAnswer(newOut, null, answer);
+ }
+ return newOut;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.state.DNSStateTask#buildOutgoingForInfo(javax.jmdns.impl.ServiceInfoImpl, javax.jmdns.impl.DNSOutgoing)
+ */
+ @Override
+ protected DNSOutgoing buildOutgoingForInfo(ServiceInfoImpl info, DNSOutgoing out) throws IOException {
+ DNSOutgoing newOut = out;
+ for (DNSRecord answer : info.answers(DNSRecordClass.UNIQUE, this.getTTL(), this.getDns().getLocalHost())) {
+ newOut = this.addAnswer(newOut, null, answer);
+ }
+ return newOut;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.state.DNSStateTask#recoverTask(java.lang.Throwable)
+ */
+ @Override
+ protected void recoverTask(Throwable e) {
+ this.getDns().recover();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.state.DNSStateTask#advanceTask()
+ */
+ @Override
+ protected void advanceTask() {
+ this.setTaskState(this.getTaskState().advance());
+ if (!this.getTaskState().isCanceling()) {
+ cancel();
+ }
+ }
+} \ No newline at end of file
diff --git a/src/javax/jmdns/impl/tasks/state/DNSStateTask.java b/src/javax/jmdns/impl/tasks/state/DNSStateTask.java
new file mode 100644
index 0000000..a0896d9
--- /dev/null
+++ b/src/javax/jmdns/impl/tasks/state/DNSStateTask.java
@@ -0,0 +1,188 @@
+// Licensed under Apache License version 2.0
+package javax.jmdns.impl.tasks.state;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.jmdns.ServiceInfo;
+import javax.jmdns.impl.DNSOutgoing;
+import javax.jmdns.impl.DNSStatefulObject;
+import javax.jmdns.impl.JmDNSImpl;
+import javax.jmdns.impl.ServiceInfoImpl;
+import javax.jmdns.impl.constants.DNSConstants;
+import javax.jmdns.impl.constants.DNSState;
+import javax.jmdns.impl.tasks.DNSTask;
+
+/**
+ * This is the root class for all state tasks. These tasks work with objects that implements the {@link javax.jmdns.impl.DNSStatefulObject} interface and therefore participate in the state machine.
+ *
+ * @author Pierre Frisch
+ */
+public abstract class DNSStateTask extends DNSTask {
+ static Logger logger1 = Logger.getLogger(DNSStateTask.class.getName());
+
+ /**
+ * By setting a 0 ttl we effectively expire the record.
+ */
+ private final int _ttl;
+
+ private static int _defaultTTL = DNSConstants.DNS_TTL;
+
+ /**
+ * The state of the task.
+ */
+ private DNSState _taskState = null;
+
+ public abstract String getTaskDescription();
+
+ public static int defaultTTL() {
+ return _defaultTTL;
+ }
+
+ /**
+ * For testing only do not use in production.
+ *
+ * @param value
+ */
+ public static void setDefaultTTL(int value) {
+ _defaultTTL = value;
+ }
+
+ /**
+ * @param jmDNSImpl
+ * @param ttl
+ */
+ public DNSStateTask(JmDNSImpl jmDNSImpl, int ttl) {
+ super(jmDNSImpl);
+ _ttl = ttl;
+ }
+
+ /**
+ * @return the ttl
+ */
+ public int getTTL() {
+ return _ttl;
+ }
+
+ /**
+ * Associate the DNS host and the service infos with this task if not already associated and in the same state.
+ *
+ * @param state
+ * target state
+ */
+ protected void associate(DNSState state) {
+ synchronized (this.getDns()) {
+ this.getDns().associateWithTask(this, state);
+ }
+ for (ServiceInfo serviceInfo : this.getDns().getServices().values()) {
+ ((ServiceInfoImpl) serviceInfo).associateWithTask(this, state);
+ }
+ }
+
+ /**
+ * Remove the DNS host and service info association with this task.
+ */
+ protected void removeAssociation() {
+ // Remove association from host to this
+ synchronized (this.getDns()) {
+ this.getDns().removeAssociationWithTask(this);
+ }
+
+ // Remove associations from services to this
+ for (ServiceInfo serviceInfo : this.getDns().getServices().values()) {
+ ((ServiceInfoImpl) serviceInfo).removeAssociationWithTask(this);
+ }
+ }
+
+ @Override
+ public void run() {
+ DNSOutgoing out = this.createOugoing();
+ try {
+ if (!this.checkRunCondition()) {
+ this.cancel();
+ return;
+ }
+ List<DNSStatefulObject> stateObjects = new ArrayList<DNSStatefulObject>();
+ // send probes for JmDNS itself
+ synchronized (this.getDns()) {
+ if (this.getDns().isAssociatedWithTask(this, this.getTaskState())) {
+ logger1.finer(this.getName() + ".run() JmDNS " + this.getTaskDescription() + " " + this.getDns().getName());
+ stateObjects.add(this.getDns());
+ out = this.buildOutgoingForDNS(out);
+ }
+ }
+ // send probes for services
+ for (ServiceInfo serviceInfo : this.getDns().getServices().values()) {
+ ServiceInfoImpl info = (ServiceInfoImpl) serviceInfo;
+
+ synchronized (info) {
+ if (info.isAssociatedWithTask(this, this.getTaskState())) {
+ logger1.fine(this.getName() + ".run() JmDNS " + this.getTaskDescription() + " " + info.getQualifiedName());
+ stateObjects.add(info);
+ out = this.buildOutgoingForInfo(info, out);
+ }
+ }
+ }
+ if (!out.isEmpty()) {
+ logger1.finer(this.getName() + ".run() JmDNS " + this.getTaskDescription() + " #" + this.getTaskState());
+ this.getDns().send(out);
+
+ // Advance the state of objects.
+ this.advanceObjectsState(stateObjects);
+ } else {
+ // Advance the state of objects.
+ this.advanceObjectsState(stateObjects);
+
+ // If we have nothing to send, another timer taskState ahead of us has done the job for us. We can cancel.
+ cancel();
+ return;
+ }
+ } catch (Throwable e) {
+ logger1.log(Level.WARNING, this.getName() + ".run() exception ", e);
+ this.recoverTask(e);
+ }
+
+ this.advanceTask();
+ }
+
+ protected abstract boolean checkRunCondition();
+
+ protected abstract DNSOutgoing buildOutgoingForDNS(DNSOutgoing out) throws IOException;
+
+ protected abstract DNSOutgoing buildOutgoingForInfo(ServiceInfoImpl info, DNSOutgoing out) throws IOException;
+
+ protected abstract DNSOutgoing createOugoing();
+
+ protected void advanceObjectsState(List<DNSStatefulObject> list) {
+ if (list != null) {
+ for (DNSStatefulObject object : list) {
+ synchronized (object) {
+ object.advanceState(this);
+ }
+ }
+ }
+ }
+
+ protected abstract void recoverTask(Throwable e);
+
+ protected abstract void advanceTask();
+
+ /**
+ * @return the taskState
+ */
+ protected DNSState getTaskState() {
+ return this._taskState;
+ }
+
+ /**
+ * @param taskState
+ * the taskState to set
+ */
+ protected void setTaskState(DNSState taskState) {
+ this._taskState = taskState;
+ }
+
+}
diff --git a/src/javax/jmdns/impl/tasks/state/Prober.java b/src/javax/jmdns/impl/tasks/state/Prober.java
new file mode 100644
index 0000000..a793a27
--- /dev/null
+++ b/src/javax/jmdns/impl/tasks/state/Prober.java
@@ -0,0 +1,161 @@
+// Copyright 2003-2005 Arthur van Hoff, Rick Blair
+// Licensed under Apache License version 2.0
+// Original license LGPL
+
+package javax.jmdns.impl.tasks.state;
+
+import java.io.IOException;
+import java.util.Timer;
+import java.util.logging.Logger;
+
+import javax.jmdns.impl.DNSOutgoing;
+import javax.jmdns.impl.DNSQuestion;
+import javax.jmdns.impl.DNSRecord;
+import javax.jmdns.impl.JmDNSImpl;
+import javax.jmdns.impl.ServiceInfoImpl;
+import javax.jmdns.impl.constants.DNSConstants;
+import javax.jmdns.impl.constants.DNSRecordClass;
+import javax.jmdns.impl.constants.DNSRecordType;
+import javax.jmdns.impl.constants.DNSState;
+
+/**
+ * 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,
+ * it launches an Announcer.
+ * <p/>
+ * 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.
+ */
+public class Prober extends DNSStateTask {
+ static Logger logger = Logger.getLogger(Prober.class.getName());
+
+ public Prober(JmDNSImpl jmDNSImpl) {
+ super(jmDNSImpl, defaultTTL());
+
+ this.setTaskState(DNSState.PROBING_1);
+ this.associate(DNSState.PROBING_1);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.DNSTask#getName()
+ */
+ @Override
+ public String getName() {
+ return "Prober(" + (this.getDns() != null ? this.getDns().getName() : "") + ")";
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return super.toString() + " state: " + this.getTaskState();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.DNSTask#start(java.util.Timer)
+ */
+ @Override
+ public void start(Timer timer) {
+ long now = System.currentTimeMillis();
+ if (now - this.getDns().getLastThrottleIncrement() < DNSConstants.PROBE_THROTTLE_COUNT_INTERVAL) {
+ this.getDns().setThrottle(this.getDns().getThrottle() + 1);
+ } else {
+ this.getDns().setThrottle(1);
+ }
+ this.getDns().setLastThrottleIncrement(now);
+
+ if (this.getDns().isAnnounced() && this.getDns().getThrottle() < DNSConstants.PROBE_THROTTLE_COUNT) {
+ timer.schedule(this, JmDNSImpl.getRandom().nextInt(1 + DNSConstants.PROBE_WAIT_INTERVAL), DNSConstants.PROBE_WAIT_INTERVAL);
+ } else if (!this.getDns().isCanceling() && !this.getDns().isCanceled()) {
+ timer.schedule(this, DNSConstants.PROBE_CONFLICT_INTERVAL, DNSConstants.PROBE_CONFLICT_INTERVAL);
+ }
+ }
+
+ @Override
+ public boolean cancel() {
+ this.removeAssociation();
+
+ return super.cancel();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.state.DNSStateTask#getTaskDescription()
+ */
+ @Override
+ public String getTaskDescription() {
+ return "probing";
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.state.DNSStateTask#checkRunCondition()
+ */
+ @Override
+ protected boolean checkRunCondition() {
+ return !this.getDns().isCanceling() && !this.getDns().isCanceled();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.state.DNSStateTask#createOugoing()
+ */
+ @Override
+ protected DNSOutgoing createOugoing() {
+ return new DNSOutgoing(DNSConstants.FLAGS_QR_QUERY);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.state.DNSStateTask#buildOutgoingForDNS(javax.jmdns.impl.DNSOutgoing)
+ */
+ @Override
+ protected DNSOutgoing buildOutgoingForDNS(DNSOutgoing out) throws IOException {
+ DNSOutgoing newOut = out;
+ newOut.addQuestion(DNSQuestion.newQuestion(this.getDns().getLocalHost().getName(), DNSRecordType.TYPE_ANY, DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE));
+ for (DNSRecord answer : this.getDns().getLocalHost().answers(DNSRecordClass.NOT_UNIQUE, this.getTTL())) {
+ newOut = this.addAuthoritativeAnswer(newOut, answer);
+ }
+ return newOut;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.state.DNSStateTask#buildOutgoingForInfo(javax.jmdns.impl.ServiceInfoImpl, javax.jmdns.impl.DNSOutgoing)
+ */
+ @Override
+ protected DNSOutgoing buildOutgoingForInfo(ServiceInfoImpl info, DNSOutgoing out) throws IOException {
+ DNSOutgoing newOut = out;
+ newOut = this.addQuestion(newOut, DNSQuestion.newQuestion(info.getQualifiedName(), DNSRecordType.TYPE_ANY, DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE));
+ // 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
+ 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()
+ .getName()));
+ return newOut;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.state.DNSStateTask#recoverTask(java.lang.Throwable)
+ */
+ @Override
+ protected void recoverTask(Throwable e) {
+ this.getDns().recover();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.state.DNSStateTask#advanceTask()
+ */
+ @Override
+ protected void advanceTask() {
+ this.setTaskState(this.getTaskState().advance());
+ if (!this.getTaskState().isProbing()) {
+ cancel();
+
+ this.getDns().startAnnouncer();
+ }
+ }
+
+} \ No newline at end of file
diff --git a/src/javax/jmdns/impl/tasks/state/Renewer.java b/src/javax/jmdns/impl/tasks/state/Renewer.java
new file mode 100644
index 0000000..f79ee12
--- /dev/null
+++ b/src/javax/jmdns/impl/tasks/state/Renewer.java
@@ -0,0 +1,144 @@
+// Copyright 2003-2005 Arthur van Hoff, Rick Blair
+// Licensed under Apache License version 2.0
+// Original license LGPL
+
+package javax.jmdns.impl.tasks.state;
+
+import java.io.IOException;
+import java.util.Timer;
+import java.util.logging.Logger;
+
+import javax.jmdns.impl.DNSOutgoing;
+import javax.jmdns.impl.DNSRecord;
+import javax.jmdns.impl.JmDNSImpl;
+import javax.jmdns.impl.ServiceInfoImpl;
+import javax.jmdns.impl.constants.DNSConstants;
+import javax.jmdns.impl.constants.DNSRecordClass;
+import javax.jmdns.impl.constants.DNSState;
+
+/**
+ * The Renewer is there to send renewal announcement when the record expire for ours infos.
+ */
+public class Renewer extends DNSStateTask {
+ static Logger logger = Logger.getLogger(Renewer.class.getName());
+
+ public Renewer(JmDNSImpl jmDNSImpl) {
+ super(jmDNSImpl, defaultTTL());
+
+ this.setTaskState(DNSState.ANNOUNCED);
+ this.associate(DNSState.ANNOUNCED);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.DNSTask#getName()
+ */
+ @Override
+ public String getName() {
+ return "Renewer(" + (this.getDns() != null ? this.getDns().getName() : "") + ")";
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return super.toString() + " state: " + this.getTaskState();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.DNSTask#start(java.util.Timer)
+ */
+ @Override
+ public void start(Timer timer) {
+ if (!this.getDns().isCanceling() && !this.getDns().isCanceled()) {
+ // BEGIN android-changed
+ // Schedule the renewer based on this task's TTL, not the default TTL
+ timer.schedule(this, getTTL() * 500, getTTL() * 500);
+ // END android-changed
+ }
+ }
+
+ @Override
+ public boolean cancel() {
+ this.removeAssociation();
+
+ return super.cancel();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.state.DNSStateTask#getTaskDescription()
+ */
+ @Override
+ public String getTaskDescription() {
+ return "renewing";
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.state.DNSStateTask#checkRunCondition()
+ */
+ @Override
+ protected boolean checkRunCondition() {
+ return !this.getDns().isCanceling() && !this.getDns().isCanceled();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.state.DNSStateTask#createOugoing()
+ */
+ @Override
+ protected DNSOutgoing createOugoing() {
+ return new DNSOutgoing(DNSConstants.FLAGS_QR_RESPONSE | DNSConstants.FLAGS_AA);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.state.DNSStateTask#buildOutgoingForDNS(javax.jmdns.impl.DNSOutgoing)
+ */
+ @Override
+ protected DNSOutgoing buildOutgoingForDNS(DNSOutgoing out) throws IOException {
+ DNSOutgoing newOut = out;
+ for (DNSRecord answer : this.getDns().getLocalHost().answers(DNSRecordClass.UNIQUE, this.getTTL())) {
+ newOut = this.addAnswer(newOut, null, answer);
+ }
+ return newOut;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.state.DNSStateTask#buildOutgoingForInfo(javax.jmdns.impl.ServiceInfoImpl, javax.jmdns.impl.DNSOutgoing)
+ */
+ @Override
+ protected DNSOutgoing buildOutgoingForInfo(ServiceInfoImpl info, DNSOutgoing out) throws IOException {
+ DNSOutgoing newOut = out;
+ for (DNSRecord answer : info.answers(DNSRecordClass.UNIQUE, this.getTTL(), this.getDns().getLocalHost())) {
+ newOut = this.addAnswer(newOut, null, answer);
+ }
+ return newOut;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.state.DNSStateTask#recoverTask(java.lang.Throwable)
+ */
+ @Override
+ protected void recoverTask(Throwable e) {
+ this.getDns().recover();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.jmdns.impl.tasks.state.DNSStateTask#advanceTask()
+ */
+ @Override
+ protected void advanceTask() {
+ this.setTaskState(this.getTaskState().advance());
+ if (!this.getTaskState().isAnnounced()) {
+ cancel();
+ }
+ }
+} \ No newline at end of file
diff --git a/src/javax/jmdns/impl/tasks/state/package-info.java b/src/javax/jmdns/impl/tasks/state/package-info.java
new file mode 100644
index 0000000..d9b986c
--- /dev/null
+++ b/src/javax/jmdns/impl/tasks/state/package-info.java
@@ -0,0 +1,2 @@
+package javax.jmdns.impl.tasks.state;
+