TH-CONECT 3.0 v版本的 MD5 值为:96be240369c9625eef513b9a5e2c5153
以下内容为反编译后的 VpnUtils.java 源代码,内容仅作参考
package com.romzkie.ultrasshservice.tunnel.vpn;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.LinkProperties;
import android.os.Build;
import com.romzkie.ultrasshservice.logger.SkStatus;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;
public class VpnUtils {
private static final String DEFAULT_PRIMARY_DNS_SERVER = "8.8.4.4";
private static final String DEFAULT_SECONDARY_DNS_SERVER = "8.8.8.8";
private static final Pattern IPV4_PATTERN = Pattern.compile("^(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}$");
private static final Pattern IPV6_STD_PATTERN = Pattern.compile("^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$");
private static final Pattern IPV6_HEX_COMPRESSED_PATTERN = Pattern.compile("^((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)::((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)$");
public static int findProcessId(String str) throws IOException {
String[] strArr = {"ps -ef", "ps -A", TunnelConstants.SHELL_CMD_PS};
int i = 0;
while (i < 3) {
Process exec = Runtime.getRuntime().exec(strArr[i]);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(exec.getInputStream()));
while (true) {
String readLine = bufferedReader.readLine();
if (readLine != null) {
if (!readLine.contains("PID") && readLine.contains(str)) {
String[] split = readLine.split("\\s+");
try {
try {
int parseInt = Integer.parseInt(split[1]);
try {
exec.destroy();
} catch (Exception unused) {
}
return parseInt;
} catch (NumberFormatException unused2) {
int parseInt2 = Integer.parseInt(split[0]);
try {
exec.destroy();
} catch (Exception unused3) {
}
return parseInt2;
}
} catch (Throwable th) {
try {
exec.destroy();
} catch (Exception unused4) {
}
throw th;
}
}
}
}
}
return -1;
}
public static void killProcess(File file) throws Exception {
killProcess(file, "-9");
}
public static int killProcess(File file, String str) throws Exception {
int i = 0;
do {
int findProcessId = findProcessId(file.getName());
if (findProcessId == -1) {
return findProcessId;
}
i++;
String valueOf = String.valueOf(findProcessId);
String[] strArr = {"", "busybox ", "toolbox "};
for (int i2 = 0; i2 < 3; i2++) {
try {
Runtime runtime = Runtime.getRuntime();
runtime.exec(strArr[i2] + "killall " + str + " " + file.getName());
} catch (IOException unused) {
}
try {
Runtime runtime2 = Runtime.getRuntime();
runtime2.exec(strArr[i2] + "killall " + str + " " + file.getCanonicalPath());
} catch (IOException unused2) {
}
}
killProcess(valueOf, str);
try {
Thread.sleep(1000L);
} catch (InterruptedException unused3) {
}
} while (i <= 4);
throw new Exception("Cannot kill: " + file.getAbsolutePath());
}
public static void killProcess(String str, String str2) throws Exception {
String[] strArr = {"", "toolbox ", "busybox "};
for (int i = 0; i < 3; i++) {
try {
Runtime runtime = Runtime.getRuntime();
runtime.exec(strArr[i] + "kill " + str2 + " " + str);
} catch (IOException e) {
SkStatus.logDebug(String.format("error killing process: %s, %s", str, e.getMessage()));
}
}
}
public static List<String> getActiveNetworkDnsResolver(Context context) throws Exception {
Collection<InetAddress> activeNetworkDnsResolvers = getActiveNetworkDnsResolvers(context);
if (!activeNetworkDnsResolvers.isEmpty()) {
ArrayList arrayList = new ArrayList();
int i = 2;
for (InetAddress inetAddress : activeNetworkDnsResolvers) {
String obj = inetAddress.toString();
if (obj.startsWith("/")) {
obj = obj.substring(1);
}
if (!obj.contains(":")) {
arrayList.add(obj);
i--;
if (i <= 0) {
break;
}
}
}
return arrayList;
}
throw new Exception("no active network DNS resolver");
}
private static Collection<InetAddress> getActiveNetworkDnsResolvers(Context context) throws Exception {
ArrayList arrayList = new ArrayList();
try {
Class<?> cls = Class.forName("android.net.LinkProperties");
Object invoke = ConnectivityManager.class.getMethod("getActiveLinkProperties", new Class[0]).invoke((ConnectivityManager) context.getSystemService("connectivity"), new Object[0]);
if (invoke != null) {
if (Build.VERSION.SDK_INT < 21) {
for (InetAddress inetAddress : (Collection) cls.getMethod("getDnses", new Class[0]).invoke(invoke, new Object[0])) {
arrayList.add(inetAddress);
}
} else {
for (InetAddress inetAddress2 : ((LinkProperties) invoke).getDnsServers()) {
arrayList.add(inetAddress2);
}
}
}
return arrayList;
} catch (ClassNotFoundException e) {
throw new Exception("getActiveNetworkDnsResolvers failed", e);
} catch (IllegalAccessException e2) {
throw new Exception("getActiveNetworkDnsResolvers failed", e2);
} catch (IllegalArgumentException e3) {
throw new Exception("getActiveNetworkDnsResolvers failed", e3);
} catch (NoSuchMethodException e4) {
throw new Exception("getActiveNetworkDnsResolvers failed", e4);
} catch (NullPointerException e5) {
throw new Exception("getActiveNetworkDnsResolvers failed", e5);
} catch (InvocationTargetException e6) {
throw new Exception("getActiveNetworkDnsResolvers failed", e6);
}
}
public static List<String> getNetworkDnsServer(Context context) {
ArrayList arrayList = new ArrayList();
try {
return getActiveNetworkDnsResolver(context);
} catch (Exception unused) {
arrayList.add(DEFAULT_PRIMARY_DNS_SERVER);
arrayList.add(DEFAULT_SECONDARY_DNS_SERVER);
return arrayList;
}
}
public static boolean isIPv4Address(String str) {
return IPV4_PATTERN.matcher(str).matches();
}
public static boolean isIPv6StdAddress(String str) {
return IPV6_STD_PATTERN.matcher(str).matches();
}
public static boolean isIPv6HexCompressedAddress(String str) {
return IPV6_HEX_COMPRESSED_PATTERN.matcher(str).matches();
}
public static boolean isIPv6Address(String str) {
return isIPv6StdAddress(str) || isIPv6HexCompressedAddress(str);
}
public static class PrivateAddress {
public final String mIpAddress;
public final int mPrefixLength;
public final String mRouter;
public final String mSubnet;
public PrivateAddress(String str, String str2, int i, String str3) {
this.mIpAddress = str;
this.mSubnet = str2;
this.mPrefixLength = i;
this.mRouter = str3;
}
}
public static PrivateAddress selectPrivateAddress() throws Exception {
HashMap hashMap = new HashMap();
hashMap.put("10", new PrivateAddress("10.0.0.1", "10.0.0.0", 8, "10.0.0.2"));
hashMap.put("172", new PrivateAddress("172.16.0.1", "172.16.0.0", 12, "172.16.0.2"));
hashMap.put("192", new PrivateAddress("192.168.0.1", "192.168.0.0", 16, "192.168.0.2"));
hashMap.put("169", new PrivateAddress("169.254.1.1", "169.254.1.0", 24, "169.254.1.2"));
try {
for (NetworkInterface networkInterface : Collections.list(NetworkInterface.getNetworkInterfaces())) {
Iterator it = Collections.list(networkInterface.getInetAddresses()).iterator();
while (it.hasNext()) {
InetAddress inetAddress = (InetAddress) it.next();
if (!inetAddress.isLoopbackAddress() && (inetAddress instanceof Inet4Address)) {
String hostAddress = inetAddress.getHostAddress();
if (hostAddress.startsWith("10.")) {
hashMap.remove("10");
} else if (hostAddress.length() >= 6 && hostAddress.substring(0, 6).compareTo("172.16") >= 0 && hostAddress.substring(0, 6).compareTo("172.31") <= 0) {
hashMap.remove("172");
} else if (hostAddress.startsWith("192.168")) {
hashMap.remove("192");
}
}
}
}
if (hashMap.size() > 0) {
return (PrivateAddress) hashMap.values().iterator().next();
}
throw new Exception("no private address available");
} catch (SocketException e) {
e.printStackTrace();
throw new Exception("selectPrivateAddress failed", e);
}
}
private static boolean isPortAvailable(int i) {
Socket socket = new Socket();
try {
try {
socket.connect(new InetSocketAddress("127.0.0.1", i), 1000);
try {
socket.close();
} catch (IOException unused) {
}
return false;
} catch (IOException unused2) {
return false;
}
} catch (SocketTimeoutException unused3) {
socket.close();
return false;
} catch (IOException unused4) {
try {
socket.close();
} catch (IOException unused5) {
}
return true;
} catch (Throwable th) {
try {
socket.close();
} catch (IOException unused6) {
}
throw th;
}
}
public static int findAvailablePort(int i, int i2) {
for (int i3 = i; i3 < i + i2; i3++) {
if (isPortAvailable(i3)) {
return i3;
}
}
return 0;
}
}