Harden Android VPN uplink transient retries
This commit is contained in:
@@ -30,8 +30,8 @@ android {
|
||||
applicationId "su.cin.rapvpn"
|
||||
minSdk 26
|
||||
targetSdk 35
|
||||
versionCode 183
|
||||
versionName "0.2.183"
|
||||
versionCode 184
|
||||
versionName "0.2.184"
|
||||
buildConfigField "String", "DEFAULT_BACKEND_URL", "\"${normalizeGradleString(defaultBackendUrl)}\""
|
||||
buildConfigField "String", "DEFAULT_CLUSTER_ID", "\"${normalizeGradleString(defaultClusterId)}\""
|
||||
buildConfigField "String", "DEFAULT_ORGANIZATION_ID", "\"${normalizeGradleString(defaultOrganizationId)}\""
|
||||
|
||||
@@ -33,6 +33,7 @@ import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
@@ -60,6 +61,9 @@ public class RapVpnService extends VpnService {
|
||||
private static final int PRIORITY_QUEUE_CAPACITY = 4096;
|
||||
private static final int UPLINK_SEND_RETRY_COUNT = 2;
|
||||
private static final int UPLINK_SEND_RETRY_SLEEP_MS = 80;
|
||||
private static final int UPLINK_TRANSIENT_RETRY_COUNT = 10;
|
||||
private static final int UPLINK_TRANSIENT_RETRY_SLEEP_MS = 250;
|
||||
private static final int UPLINK_TRANSIENT_RETRY_MAX_SLEEP_MS = 1500;
|
||||
private static final int DOWNLINK_QUEUE_CAPACITY = 8192;
|
||||
private static final int DOWNLINK_FLOW_QUEUE_MAX_COUNT = 8;
|
||||
private static final int DOWNLINK_QUEUE_OFFER_MS = 50;
|
||||
@@ -2475,7 +2479,8 @@ public class RapVpnService extends VpnService {
|
||||
return true;
|
||||
}
|
||||
RapApiClient client = packetRelayClientForUrl(relayUrl);
|
||||
for (int attempt = 0; attempt <= UPLINK_SEND_RETRY_COUNT && running; attempt++) {
|
||||
int attempt = 0;
|
||||
while (running) {
|
||||
try {
|
||||
client.sendClientPacketBatch(clusterId, vpnConnectionId, batch);
|
||||
if (attempt > 0) {
|
||||
@@ -2486,7 +2491,16 @@ public class RapVpnService extends VpnService {
|
||||
lastError = e;
|
||||
lastUplinkSendErrorMessage = compactException(e);
|
||||
writeRuntimeDetail("retry", "uplink send retry worker=" + workerIndex + " relay=" + relayUrl + " attempt=" + attempt + " error=" + lastUplinkSendErrorMessage, "uplink_sender", -1, -1, e.getClass().getSimpleName(), workerIndex);
|
||||
sleepQuietly(UPLINK_SEND_RETRY_SLEEP_MS * (attempt + 1L));
|
||||
boolean transientError = isTransientUplinkSendError(e);
|
||||
int retryLimit = transientError ? UPLINK_TRANSIENT_RETRY_COUNT : UPLINK_SEND_RETRY_COUNT;
|
||||
if (attempt >= retryLimit) {
|
||||
break;
|
||||
}
|
||||
int baseSleepMs = transientError ? UPLINK_TRANSIENT_RETRY_SLEEP_MS : UPLINK_SEND_RETRY_SLEEP_MS;
|
||||
int maxSleepMs = transientError ? UPLINK_TRANSIENT_RETRY_MAX_SLEEP_MS : UPLINK_SEND_RETRY_SLEEP_MS * (UPLINK_SEND_RETRY_COUNT + 1);
|
||||
long sleepMs = Math.min(maxSleepMs, baseSleepMs * (attempt + 1L));
|
||||
sleepQuietly(sleepMs);
|
||||
attempt++;
|
||||
}
|
||||
}
|
||||
if (!switchPacketRelayUrl(relayUrl, lastError == null ? "send_failed" : lastError.getClass().getSimpleName())) {
|
||||
@@ -2499,6 +2513,20 @@ public class RapVpnService extends VpnService {
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isTransientUplinkSendError(Exception e) {
|
||||
String message = e == null ? null : e.getMessage();
|
||||
if (message == null) {
|
||||
return false;
|
||||
}
|
||||
String lower = message.toLowerCase(Locale.ROOT);
|
||||
return lower.contains("http 502")
|
||||
|| lower.contains("http 503")
|
||||
|| lower.contains("http 504")
|
||||
|| lower.contains("mesh synthetic route not found")
|
||||
|| lower.contains("forward runtime unavailable")
|
||||
|| lower.contains("forward peer unavailable");
|
||||
}
|
||||
|
||||
private boolean sendUplinkBatchOverWebSocket(String relayUrl, String clusterId, String vpnConnectionId, List<byte[]> batch, int workerIndex) {
|
||||
if (!PACKET_WEBSOCKET_DATAPLANE_ENABLED) {
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user