Prioritize Android WebSocket downlink packets
This commit is contained in:
@@ -30,8 +30,8 @@ android {
|
||||
applicationId "su.cin.rapvpn"
|
||||
minSdk 26
|
||||
targetSdk 35
|
||||
versionCode 201
|
||||
versionName "0.2.201"
|
||||
versionCode 202
|
||||
versionName "0.2.202"
|
||||
buildConfigField "String", "DEFAULT_BACKEND_URL", "\"${normalizeGradleString(defaultBackendUrl)}\""
|
||||
buildConfigField "String", "DEFAULT_CLUSTER_ID", "\"${normalizeGradleString(defaultClusterId)}\""
|
||||
buildConfigField "String", "DEFAULT_ORGANIZATION_ID", "\"${normalizeGradleString(defaultOrganizationId)}\""
|
||||
|
||||
@@ -31,6 +31,7 @@ final class VpnPacketWebSocketRelay {
|
||||
private final VpnService vpnService;
|
||||
private final OkHttpClient httpClient;
|
||||
private final FabricServiceChannel fabricServiceChannel;
|
||||
private final BlockingQueue<List<byte[]>> priorityIncoming = new ArrayBlockingQueue<>(512);
|
||||
private final BlockingQueue<List<byte[]>> incoming = new ArrayBlockingQueue<>(2048);
|
||||
private final Object lock = new Object();
|
||||
|
||||
@@ -153,7 +154,19 @@ final class VpnPacketWebSocketRelay {
|
||||
connect(clusterId, vpnConnectionId);
|
||||
awaitOpen(Math.min(OPEN_WAIT_MS, Math.max(1, timeoutMs)));
|
||||
int waitMs = Math.max(1, timeoutMs);
|
||||
List<byte[]> packets = incoming.poll(waitMs, TimeUnit.MILLISECONDS);
|
||||
List<byte[]> packets = priorityIncoming.poll();
|
||||
if (packets != null) {
|
||||
return packets;
|
||||
}
|
||||
packets = incoming.poll(Math.min(2, waitMs), TimeUnit.MILLISECONDS);
|
||||
if (packets != null) {
|
||||
return packets;
|
||||
}
|
||||
packets = priorityIncoming.poll();
|
||||
if (packets != null) {
|
||||
return packets;
|
||||
}
|
||||
packets = incoming.poll(Math.max(1, waitMs - 2), TimeUnit.MILLISECONDS);
|
||||
return packets == null ? new ArrayList<>() : packets;
|
||||
}
|
||||
|
||||
@@ -167,6 +180,7 @@ final class VpnPacketWebSocketRelay {
|
||||
open = false;
|
||||
connecting = false;
|
||||
connectingSinceMs = 0;
|
||||
priorityIncoming.clear();
|
||||
incoming.clear();
|
||||
if (webSocket != null) {
|
||||
try {
|
||||
@@ -238,10 +252,7 @@ final class VpnPacketWebSocketRelay {
|
||||
if (packets.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (!incoming.offer(packets)) {
|
||||
incoming.poll();
|
||||
incoming.offer(packets);
|
||||
}
|
||||
offerIncomingPacketBatch(packets);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -333,6 +344,38 @@ final class VpnPacketWebSocketRelay {
|
||||
return packets;
|
||||
}
|
||||
|
||||
private void offerIncomingPacketBatch(List<byte[]> packets) {
|
||||
BlockingQueue<List<byte[]>> target = containsTCPControlPacket(packets) ? priorityIncoming : incoming;
|
||||
if (!target.offer(packets)) {
|
||||
target.poll();
|
||||
target.offer(packets);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean containsTCPControlPacket(List<byte[]> packets) {
|
||||
if (packets == null) {
|
||||
return false;
|
||||
}
|
||||
for (byte[] packet : packets) {
|
||||
if (isTCPControlPacket(packet)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isTCPControlPacket(byte[] packet) {
|
||||
if (packet == null || packet.length < 20 || (packet[0] >> 4) != 4) {
|
||||
return false;
|
||||
}
|
||||
int ihl = (packet[0] & 0x0f) * 4;
|
||||
if (ihl < 20 || packet.length < ihl + 20 || packet[9] != 6) {
|
||||
return false;
|
||||
}
|
||||
int flags = packet[ihl + 13] & 0xff;
|
||||
return (flags & 0x17) != 0;
|
||||
}
|
||||
|
||||
private static String trimRight(String value) {
|
||||
if (value == null) {
|
||||
return "";
|
||||
|
||||
Reference in New Issue
Block a user