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