小麦加速 v1.3.6版本的 MD5 值为:6f7d4520f96ba41559a0daa8b426cc14

以下内容为反编译后的 TunService.java 源代码,内容仅作参考


package com.github.kr328.clash.service;

import android.app.PendingIntent;
import android.content.Intent;
import android.net.ProxyInfo;
import android.net.VpnService;
import android.os.Build;
import android.os.ParcelFileDescriptor;
import com.facebook.react.modules.systeminfo.AndroidInfoHelpers;
import com.github.kr328.clash.common.compat.IntentsKt;
import com.github.kr328.clash.common.constants.Components;
import com.github.kr328.clash.common.log.Log;
import com.github.kr328.clash.service.clash.ClashRuntime;
import com.github.kr328.clash.service.clash.ClashRuntimeKt;
import com.github.kr328.clash.service.clash.module.StaticNotificationModule;
import com.github.kr328.clash.service.clash.module.TunModule;
import com.github.kr328.clash.service.model.AccessControlMode;
import com.github.kr328.clash.service.store.ServiceStore;
import com.github.kr328.clash.service.util.BroadcastKt;
import com.github.kr328.clash.service.util.CoroutineKt;
import com.github.kr328.clash.service.util.IPNet;
import com.github.kr328.clash.service.util.NetKt;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import kotlin.Metadata;
import kotlin.Result;
import kotlin.ResultKt;
import kotlin.collections.CollectionsKt;
import kotlin.collections.SetsKt;
import kotlin.coroutines.CoroutineContext;
import kotlin.jvm.internal.Intrinsics;
import kotlinx.coroutines.CoroutineScope;
import kotlinx.coroutines.CoroutineScopeKt;
import kotlinx.coroutines.Dispatchers;

@Metadata(d1 = {"\u0000D\n\u0002\u0018\u0002\n\u0002\u0018\u0002\n\u0002\u0018\u0002\n\u0002\b\u0002\n\u0002\u0018\u0002\n\u0002\b\u0003\n\u0002\u0010\u000e\n\u0000\n\u0002\u0018\u0002\n\u0002\b\u0004\n\u0002\u0010\u0002\n\u0002\b\u0002\n\u0002\u0010\b\n\u0000\n\u0002\u0018\u0002\n\u0002\b\u0005\n\u0002\u0018\u0002\n\u0002\b\u0002\u0018\u0000 \u001c2\u00020\u00012\u00020\u0002:\u0001\u001cB\u0005¢\u0006\u0002\u0010\u0003J\b\u0010\u000f\u001a\u00020\u0010H\u0016J\b\u0010\u0011\u001a\u00020\u0010H\u0016J\"\u0010\u0012\u001a\u00020\u00132\b\u0010\u0014\u001a\u0004\u0018\u00010\u00152\u0006\u0010\u0016\u001a\u00020\u00132\u0006\u0010\u0017\u001a\u00020\u0013H\u0016J\u0010\u0010\u0018\u001a\u00020\u00102\u0006\u0010\u0019\u001a\u00020\u0013H\u0016J\f\u0010\u001a\u001a\u00020\u0010*\u00020\u001bH\u0002R\u0012\u0010\u0004\u001a\u00020\u0005X\u0096\u0005¢\u0006\u0006\u001a\u0004\b\u0006\u0010\u0007R\u0010\u0010\b\u001a\u0004\u0018\u00010\tX\u0082\u000e¢\u0006\u0002\n\u0000R\u000e\u0010\n\u001a\u00020\u000bX\u0082\u0004¢\u0006\u0002\n\u0000R\u0014\u0010\f\u001a\u00020\u00008BX\u0082\u0004¢\u0006\u0006\u001a\u0004\b\r\u0010\u000e¨\u0006\u001d"}, d2 = {"Lcom/github/kr328/clash/service/TunService;", "Landroid/net/VpnService;", "Lkotlinx/coroutines/CoroutineScope;", "()V", "coroutineContext", "Lkotlin/coroutines/CoroutineContext;", "getCoroutineContext", "()Lkotlin/coroutines/CoroutineContext;", "reason", "", "runtime", "Lcom/github/kr328/clash/service/clash/ClashRuntime;", "self", "getSelf", "()Lcom/github/kr328/clash/service/TunService;", "onCreate", "", "onDestroy", "onStartCommand", "", "intent", "Landroid/content/Intent;", "flags", "startId", "onTrimMemory", "level", "open", "Lcom/github/kr328/clash/service/clash/module/TunModule;", "Companion", "service_meta-alphaRelease"}, k = 1, mv = {1, 7, 1}, xi = 48)
public final class TunService extends VpnService implements CoroutineScope {
    private static final String NET_ANY = "0.0.0.0";
    private static final String TUN_DNS = "172.19.0.2";
    private static final String TUN_GATEWAY = "172.19.0.1";
    private static final int TUN_MTU = 9000;
    private static final String TUN_PORTAL = "172.19.0.2";
    private static final int TUN_SUBNET_PREFIX = 30;
    private String reason;
    private static final List<String> HTTP_PROXY_LOCAL_LIST = CollectionsKt.listOf((Object[]) new String[]{AndroidInfoHelpers.DEVICE_LOCALHOST, "*.local", "127.*", "10.*", "172.16.*", "172.17.*", "172.18.*", "172.19.*", "172.2*", "172.30.*", "172.31.*", "192.168.*"});
    private static final List<String> HTTP_PROXY_BLACK_LIST = CollectionsKt.listOf((Object[]) new String[]{"*zhihu.com", "*zhimg.com", "*jd.com", "100ime-iat-api.xfyun.cn"});
    private final CoroutineScope $$delegate_0 = CoroutineScopeKt.CoroutineScope(Dispatchers.getDefault());
    private final ClashRuntime runtime = ClashRuntimeKt.clashRuntime(this, new TunService$runtime$1(this, null));

    @Metadata(k = 3, mv = {1, 7, 1}, xi = 48)
    public class WhenMappings {
        public static final int[] $EnumSwitchMapping$0;

        static {
            int[] iArr = new int[AccessControlMode.values().length];
            iArr[AccessControlMode.AcceptAll.ordinal()] = 1;
            iArr[AccessControlMode.AcceptSelected.ordinal()] = 2;
            iArr[AccessControlMode.DenySelected.ordinal()] = 3;
            $EnumSwitchMapping$0 = iArr;
        }
    }

    public final TunService getSelf() {
        return this;
    }

    @Override
    public CoroutineContext getCoroutineContext() {
        return this.$$delegate_0.getCoroutineContext();
    }

    @Override
    public void onCreate() {
        super.onCreate();
        if (StatusProvider.INSTANCE.getServiceRunning()) {
            stopSelf();
            return;
        }
        StatusProvider.INSTANCE.setServiceRunning(true);
        TunService tunService = this;
        StaticNotificationModule.INSTANCE.createNotificationChannel(tunService);
        StaticNotificationModule.INSTANCE.notifyLoadingNotification(tunService);
        this.runtime.launch();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        BroadcastKt.sendClashStarted(this);
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        TunModule.INSTANCE.requestStop();
        StatusProvider.INSTANCE.setServiceRunning(false);
        BroadcastKt.sendClashStopped(this, this.reason);
        CoroutineKt.cancelAndJoinBlocking(this);
        Log log = Log.INSTANCE;
        StringBuilder sb = new StringBuilder();
        sb.append("TunService destroyed: ");
        String str = this.reason;
        if (str == null) {
            str = "successfully";
        }
        sb.append(str);
        Log.i$default(log, sb.toString(), null, 2, null);
        super.onDestroy();
    }

    @Override
    public void onTrimMemory(int level) {
        super.onTrimMemory(level);
        this.runtime.requestGc();
    }

    public final void open(TunModule tunModule) {
        InetSocketAddress listenHttp;
        ServiceStore serviceStore = new ServiceStore(getSelf());
        VpnService.Builder builder = new VpnService.Builder(this);
        builder.addAddress(TUN_GATEWAY, 30);
        boolean bypassPrivateNetwork = serviceStore.getBypassPrivateNetwork();
        String str = NET_ANY;
        if (bypassPrivateNetwork) {
            String[] stringArray = getResources().getStringArray(R.array.bypass_private_route);
            Intrinsics.checkNotNullExpressionValue(stringArray, "resources.getStringArray…ray.bypass_private_route)");
            String[] strArr = stringArray;
            ArrayList<IPNet> arrayList = new ArrayList(strArr.length);
            for (String str2 : strArr) {
                arrayList.add(NetKt.parseCIDR(str2));
            }
            for (IPNet iPNet : arrayList) {
                builder.addRoute(iPNet.getIp(), iPNet.getPrefix());
            }
            builder.addRoute("172.19.0.2", 32);
        } else {
            builder.addRoute(NET_ANY, 0);
        }
        int i = WhenMappings.$EnumSwitchMapping$0[serviceStore.getAccessControlMode().ordinal()];
        if (i == 2) {
            for (String str3 : SetsKt.plus(serviceStore.getAccessControlPackages(), getPackageName())) {
                try {
                    Result.Companion companion = Result.INSTANCE;
                    Result.m126constructorimpl(builder.addAllowedApplication(str3));
                } catch (Throwable th) {
                    Result.Companion companion2 = Result.INSTANCE;
                    Result.m126constructorimpl(ResultKt.createFailure(th));
                }
            }
        } else if (i == 3) {
            for (String str4 : SetsKt.minus(serviceStore.getAccessControlPackages(), getPackageName())) {
                try {
                    Result.Companion companion3 = Result.INSTANCE;
                    Result.m126constructorimpl(builder.addDisallowedApplication(str4));
                } catch (Throwable th2) {
                    Result.Companion companion4 = Result.INSTANCE;
                    Result.m126constructorimpl(ResultKt.createFailure(th2));
                }
            }
        }
        builder.setBlocking(false);
        builder.setMtu(TUN_MTU);
        builder.setSession("Clash");
        builder.addDnsServer("172.19.0.2");
        builder.setConfigureIntent(PendingIntent.getActivity(getSelf(), R.id.nf_vpn_status, new Intent().setComponent(Components.INSTANCE.getMAIN_ACTIVITY()), IntentsKt.pendingIntentFlags$default(134217728, false, 2, null)));
        if (Build.VERSION.SDK_INT >= 29) {
            builder.setMetered(false);
        }
        if (Build.VERSION.SDK_INT >= 29 && serviceStore.getSystemProxy() && (listenHttp = tunModule.listenHttp()) != null) {
            builder.setHttpProxy(ProxyInfo.buildDirectProxy(listenHttp.getAddress().getHostAddress(), listenHttp.getPort(), CollectionsKt.plus((Collection) HTTP_PROXY_BLACK_LIST, (Iterable) (serviceStore.getBypassPrivateNetwork() ? HTTP_PROXY_LOCAL_LIST : CollectionsKt.emptyList()))));
        }
        if (serviceStore.getAllowBypass()) {
            builder.allowBypass();
        }
        ParcelFileDescriptor establish = builder.establish();
        if (establish == null) {
            throw new NullPointerException("Establish VPN rejected by system");
        }
        int detachFd = establish.detachFd();
        if (!serviceStore.getDnsHijacking()) {
            str = "172.19.0.2";
        }
        tunModule.attach(new TunModule.TunDevice(detachFd, "172.19.0.1/30", "172.19.0.2", str));
    }
}