diff --git a/src/main/java/org/ice4j/ice/Agent.java b/src/main/java/org/ice4j/ice/Agent.java
index 901bb9ce..bfa31d99 100644
--- a/src/main/java/org/ice4j/ice/Agent.java
+++ b/src/main/java/org/ice4j/ice/Agent.java
@@ -121,7 +121,7 @@ public class Agent
* The ScheduledExecutorService to execute Agent's scheduled tasks
*/
private static final ScheduledExecutorService agentTasksScheduler
- = ExecutorFactory.createCPUBoundScheduledExecutor(
+ = ExecutorFactory.createSingleThreadScheduledExecutor(
"ice4j.Agent-timer-", 60, TimeUnit.SECONDS);
/**
diff --git a/src/main/java/org/ice4j/stack/StunClientTransaction.java b/src/main/java/org/ice4j/stack/StunClientTransaction.java
index cac4d310..553947f1 100644
--- a/src/main/java/org/ice4j/stack/StunClientTransaction.java
+++ b/src/main/java/org/ice4j/stack/StunClientTransaction.java
@@ -18,6 +18,7 @@
package org.ice4j.stack;
import java.io.*;
+import java.time.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import java.util.logging.*;
@@ -74,12 +75,21 @@ public class StunClientTransaction
public static final int DEFAULT_ORIGINAL_WAIT_INTERVAL = 100;
/**
- * The pool of Threads which retransmit
+ * The pool of Threads which schedules retransmission of
* StunClientTransactions.
*/
- private static final ScheduledExecutorService retransmissionThreadPool
- = ExecutorFactory.createCPUBoundScheduledExecutor(
- "ice4j.StunClientTransaction-", 60, TimeUnit.SECONDS);
+ private static final ScheduledExecutorService retransmissionTimer
+ = ExecutorFactory.createSingleThreadScheduledExecutor(
+ "ice4j.StunClientTransaction-timer-", 60, TimeUnit.SECONDS);
+
+ /**
+ * The pool of Threads which retransmits
+ * StunClientTransactions.
+ */
+ private static final ExecutorService retransmissionExecutor
+ = ExecutorFactory.createCachedThreadPool(
+ "ice4j.StunClientTransaction-executor-");
+
/**
* Maximum number of retransmissions. Once this number is reached and if no
@@ -415,7 +425,7 @@ public TransportAddress getRemoteAddress()
* If no response is received by 1.6 seconds after the last request has been
* sent, we consider the transaction to have failed.
*/
- private final class Retransmitter
+ private final class Retransmitter extends PeriodicRunnable
{
/**
* Current number of retransmission attempts
@@ -427,30 +437,28 @@ private final class Retransmitter
*/
private int nextRetransmissionDelay = originalWaitInterval;
- /**
- * Currently scheduled retransmission task
- */
- private ScheduledFuture> retransmissionFuture;
+ protected Retransmitter()
+ {
+ super(retransmissionTimer, retransmissionExecutor);
+ }
- /**
- * The scheduled runnable that perform retransmit attempt
- */
- private final Runnable retransmissionAttempt = new Runnable()
+ @Override
+ protected Duration getDelayUntilNextRun()
{
- @Override
- public void run()
- {
- if (cancelled.get())
- {
- return;
- }
+ return Duration.ofMillis(nextRetransmissionDelay);
+ }
- retransmissionCounter++;
+ @Override
+ protected void run()
+ {
+ retransmissionCounter++;
- int curWaitInterval = nextRetransmissionDelay;
- nextRetransmissionDelay
- = Math.min(maxWaitInterval, 2 * nextRetransmissionDelay);
+ int curWaitInterval = nextRetransmissionDelay;
+ nextRetransmissionDelay
+ = Math.min(maxWaitInterval, 2 * nextRetransmissionDelay);
+ if (retransmissionCounter <= maxRetransmissions)
+ {
try
{
logger.fine(
@@ -470,50 +478,9 @@ public void run()
"A client tran retransmission failed",
ex);
}
-
- if(!cancelled.get())
- {
- reschedule();
- }
}
-
- private void reschedule()
+ else
{
- if (retransmissionCounter < maxRetransmissions)
- {
- retransmissionFuture = retransmissionThreadPool.schedule(
- retransmissionAttempt,
- nextRetransmissionDelay,
- TimeUnit.MILLISECONDS);
- }
- else
- {
- // before stating that a transaction has timeout-ed we
- // should first wait for a reception of the response
- nextRetransmissionDelay =
- Math.min(maxWaitInterval, 2* nextRetransmissionDelay);
-
- retransmissionFuture = retransmissionThreadPool.schedule(
- transactionTimedOut,
- nextRetransmissionDelay,
- TimeUnit.MILLISECONDS);
- }
- }
- };
-
- /**
- * Scheduled runnable to time-out STUN transaction
- */
- private final Runnable transactionTimedOut = new Runnable()
- {
- @Override
- public void run()
- {
- if (cancelled.get())
- {
- return;
- }
-
stackCallback.removeClientTransaction(
StunClientTransaction.this);
@@ -521,36 +488,8 @@ public void run()
new StunTimeoutEvent(
stackCallback,
getRequest(), getLocalAddress(), getTransactionID()));
- }
- };
- /**
- * Schedules STUN transaction retransmission
- */
- void schedule()
- {
- if (retransmissionFuture != null)
- {
- return;
- }
-
- retransmissionFuture = retransmissionThreadPool.schedule(
- retransmissionAttempt,
- nextRetransmissionDelay,
- TimeUnit.MILLISECONDS);
- }
-
- /**
- * Cancels the transaction. Once this method is called the transaction
- * is considered terminated and will stop retransmissions.
- */
- void cancel()
- {
- final ScheduledFuture> retransmissionFuture =
- this.retransmissionFuture;
- if (retransmissionFuture != null)
- {
- retransmissionFuture.cancel(true);
+ nextRetransmissionDelay = -1;
}
}
}