From ad0dd1d63f22edc2ca43b19e5463abd2d0aefce2 Mon Sep 17 00:00:00 2001 From: arm64v8a <48624112+arm64v8a@users.noreply.github.com> Date: Sat, 1 Jul 2023 18:07:25 +0900 Subject: [PATCH] optimize code --- .../java/io/nekohasekai/sagernet/SagerNet.kt | 102 +----------------- .../sagernet/bg/proto/BoxInstance.kt | 23 ++-- .../nekohasekai/sagernet/fmt/ConfigBuilder.kt | 20 ++-- .../sagernet/utils/DeviceStorageApp.kt | 20 ---- .../java/moe/matsuri/nb4a/NativeInterface.kt | 96 +++++++++++++++++ buildScript/lib/core/get_source_env.sh | 2 +- libcore/dns.go | 13 +-- libcore/nb4a.go | 12 +-- libcore/platform_java.go | 9 +- 9 files changed, 133 insertions(+), 164 deletions(-) delete mode 100644 app/src/main/java/io/nekohasekai/sagernet/utils/DeviceStorageApp.kt create mode 100644 app/src/main/java/moe/matsuri/nb4a/NativeInterface.kt diff --git a/app/src/main/java/io/nekohasekai/sagernet/SagerNet.kt b/app/src/main/java/io/nekohasekai/sagernet/SagerNet.kt index 91c6632..b65a353 100644 --- a/app/src/main/java/io/nekohasekai/sagernet/SagerNet.kt +++ b/app/src/main/java/io/nekohasekai/sagernet/SagerNet.kt @@ -6,8 +6,6 @@ import android.content.ClipData import android.content.ClipboardManager import android.content.Context import android.content.Intent -import android.content.pm.PackageInfo -import android.content.pm.PackageManager import android.content.res.Configuration import android.net.ConnectivityManager import android.net.Network @@ -20,27 +18,21 @@ import androidx.core.content.ContextCompat import androidx.core.content.getSystemService import go.Seq import io.nekohasekai.sagernet.bg.SagerConnection -import io.nekohasekai.sagernet.bg.ServiceNotification import io.nekohasekai.sagernet.database.DataStore -import io.nekohasekai.sagernet.database.SagerDatabase import io.nekohasekai.sagernet.ktx.Logs import io.nekohasekai.sagernet.ktx.runOnDefaultDispatcher import io.nekohasekai.sagernet.ui.MainActivity import io.nekohasekai.sagernet.utils.* import kotlinx.coroutines.DEBUG_PROPERTY_NAME import kotlinx.coroutines.DEBUG_PROPERTY_VALUE_ON -import libcore.BoxPlatformInterface import libcore.Libcore -import libcore.NB4AInterface +import moe.matsuri.nb4a.NativeInterface import moe.matsuri.nb4a.utils.JavaUtil -import moe.matsuri.nb4a.utils.LibcoreUtil import moe.matsuri.nb4a.utils.cleanWebview -import java.net.InetSocketAddress import androidx.work.Configuration as WorkConfiguration class SagerNet : Application(), - BoxPlatformInterface, - WorkConfiguration.Provider, NB4AInterface { + WorkConfiguration.Provider { override fun attachBaseContext(base: Context) { super.attachBaseContext(base) @@ -48,6 +40,8 @@ class SagerNet : Application(), application = this } + val nativeInterface = NativeInterface() + val externalAssets by lazy { getExternalFilesDir(null) ?: filesDir } val process = JavaUtil.getProcessName() val isMainProcess = process == BuildConfig.APPLICATION_ID @@ -81,12 +75,9 @@ class SagerNet : Application(), externalAssets.absolutePath + "/", DataStore.logBufSize, DataStore.logLevel > 0, - this + nativeInterface, nativeInterface ) - // libbox: platform interface - Libcore.setBoxPlatformInterface(this) - if (isMainProcess) { Theme.apply(this) Theme.applyNightTheme() @@ -133,11 +124,6 @@ class SagerNet : Application(), uiMode.currentModeType == Configuration.UI_MODE_TYPE_TELEVISION } - // /data/user_de available when not unlocked - val deviceStorage by lazy { - if (Build.VERSION.SDK_INT < 24) application else DeviceStorageApp(application) - } - val configureIntent: (Context) -> PendingIntent by lazy { { PendingIntent.getActivity( @@ -209,82 +195,4 @@ class SagerNet : Application(), } - - // libbox interface - - override fun autoDetectInterfaceControl(fd: Int) { - DataStore.vpnService?.protect(fd) - } - - override fun openTun(singTunOptionsJson: String, tunPlatformOptionsJson: String): Long { - if (DataStore.vpnService == null) { - throw Exception("no VpnService") - } - return DataStore.vpnService!!.startVpn(singTunOptionsJson, tunPlatformOptionsJson).toLong() - } - - override fun useProcFS(): Boolean { - return Build.VERSION.SDK_INT < Build.VERSION_CODES.Q - } - - @RequiresApi(Build.VERSION_CODES.Q) - override fun findConnectionOwner( - ipProto: Int, srcIp: String, srcPort: Int, destIp: String, destPort: Int - ): Int { - return connectivity.getConnectionOwnerUid( - ipProto, InetSocketAddress(srcIp, srcPort), InetSocketAddress(destIp, destPort) - ) - } - - override fun packageNameByUid(uid: Int): String { - PackageCache.awaitLoadSync() - - if (uid <= 1000L) { - return "android" - } - - val packageNames = PackageCache.uidMap[uid] - if (!packageNames.isNullOrEmpty()) for (packageName in packageNames) { - return packageName - } - - error("unknown uid $uid") - } - - override fun uidByPackageName(packageName: String): Int { - PackageCache.awaitLoadSync() - return PackageCache[packageName] ?: 0 - } - - // nb4a interface - - override fun useOfficialAssets(): Boolean { - return DataStore.rulesProvider == 0 - } - - override fun selector_OnProxySelected(selectorTag: String, tag: String) { - if (selectorTag != "proxy") { - Logs.d("other selector: $selectorTag") - return - } - LibcoreUtil.resetAllConnections(true) - DataStore.baseService?.apply { - runOnDefaultDispatcher { - val id = data.proxy!!.config.profileTagMap - .filterValues { it == tag }.keys.firstOrNull() ?: -1 - val ent = SagerDatabase.proxyDao.getById(id) ?: return@runOnDefaultDispatcher - // traffic & title - data.proxy?.apply { - looper?.selectMain(id) - displayProfileName = ServiceNotification.genTitle(ent) - data.notification?.postNotificationTitle(displayProfileName) - } - // post binder - data.binder.broadcast { b -> - b.cbSelectorUpdate(id) - } - } - } - } - } diff --git a/app/src/main/java/io/nekohasekai/sagernet/bg/proto/BoxInstance.kt b/app/src/main/java/io/nekohasekai/sagernet/bg/proto/BoxInstance.kt index d1a5e99..f94d168 100644 --- a/app/src/main/java/io/nekohasekai/sagernet/bg/proto/BoxInstance.kt +++ b/app/src/main/java/io/nekohasekai/sagernet/bg/proto/BoxInstance.kt @@ -1,6 +1,5 @@ package io.nekohasekai.sagernet.bg.proto -import android.os.Build import android.os.SystemClock import io.nekohasekai.sagernet.SagerNet import io.nekohasekai.sagernet.bg.AbstractInstance @@ -117,10 +116,8 @@ abstract class BoxInstance( override fun launch() { // TODO move, this is not box - val context = - if (Build.VERSION.SDK_INT < 24 || SagerNet.user.isUserUnlocked) SagerNet.application else SagerNet.deviceStorage - val cache = File(context.cacheDir, "tmpcfg") - cache.mkdirs() + val cacheDir = File(SagerNet.application.cacheDir, "tmpcfg") + cacheDir.mkdirs() for ((chain) in config.externalIndex) { chain.entries.forEachIndexed { index, (port, profile) -> @@ -135,7 +132,7 @@ abstract class BoxInstance( bean is TrojanGoBean -> { val configFile = File( - cache, "trojan_go_" + SystemClock.elapsedRealtime() + ".json" + cacheDir, "trojan_go_" + SystemClock.elapsedRealtime() + ".json" ) configFile.parentFile?.mkdirs() configFile.writeText(config) @@ -150,7 +147,7 @@ abstract class BoxInstance( bean is NaiveBean -> { val configFile = File( - cache, "naive_" + SystemClock.elapsedRealtime() + ".json" + cacheDir, "naive_" + SystemClock.elapsedRealtime() + ".json" ) configFile.parentFile?.mkdirs() @@ -161,7 +158,7 @@ abstract class BoxInstance( if (bean.certificates.isNotBlank()) { val certFile = File( - cache, "naive_" + SystemClock.elapsedRealtime() + ".crt" + cacheDir, "naive_" + SystemClock.elapsedRealtime() + ".crt" ) certFile.parentFile?.mkdirs() @@ -180,7 +177,7 @@ abstract class BoxInstance( bean is HysteriaBean -> { val configFile = File( - cache, "hysteria_" + SystemClock.elapsedRealtime() + ".json" + cacheDir, "hysteria_" + SystemClock.elapsedRealtime() + ".json" ) configFile.parentFile?.mkdirs() @@ -213,7 +210,7 @@ abstract class BoxInstance( any as JSONObject val name = any.getString("name") - val configFile = File(cache, name) + val configFile = File(cacheDir, name) configFile.parentFile?.mkdirs() val content = any.getString("content") configFile.writeText(content) @@ -243,10 +240,8 @@ abstract class BoxInstance( } bean is TuicBean -> { - val configFile = File( - context.noBackupFilesDir, - "tuic_" + SystemClock.elapsedRealtime() + ".json" - ) + val configFile = + File(cacheDir, "tuic_" + SystemClock.elapsedRealtime() + ".json") configFile.parentFile?.mkdirs() configFile.writeText(config) diff --git a/app/src/main/java/io/nekohasekai/sagernet/fmt/ConfigBuilder.kt b/app/src/main/java/io/nekohasekai/sagernet/fmt/ConfigBuilder.kt index 40dda4a..6ff7873 100644 --- a/app/src/main/java/io/nekohasekai/sagernet/fmt/ConfigBuilder.kt +++ b/app/src/main/java/io/nekohasekai/sagernet/fmt/ConfigBuilder.kt @@ -422,24 +422,22 @@ fun buildConfig( } catch (_: Exception) { } + // domain_strategy + pastEntity?.requireBean()?.apply { + // don't loopback + if (currentDomainStrategy != "" && !serverAddress.isIpAddress()) { + domainListDNSDirectForce.add("full:$serverAddress") + } + } + currentOutbound["domain_strategy"] = if (forTest) "" else currentDomainStrategy + // custom JSON merge if (bean.customOutboundJson.isNotBlank()) { Util.mergeJSON(bean.customOutboundJson, currentOutbound) } } - pastEntity?.requireBean()?.apply { - // don't loopback - if (currentDomainStrategy != "" && !serverAddress.isIpAddress()) { - domainListDNSDirectForce.add("full:$serverAddress") - } - } - if (forTest) { - currentDomainStrategy = "" - } - currentOutbound["tag"] = tagOut - currentOutbound["domain_strategy"] = currentDomainStrategy // External proxy need a dokodemo-door inbound to forward the traffic // For external proxy software, their traffic must goes to v2ray-core to use protected fd. diff --git a/app/src/main/java/io/nekohasekai/sagernet/utils/DeviceStorageApp.kt b/app/src/main/java/io/nekohasekai/sagernet/utils/DeviceStorageApp.kt deleted file mode 100644 index fc4f632..0000000 --- a/app/src/main/java/io/nekohasekai/sagernet/utils/DeviceStorageApp.kt +++ /dev/null @@ -1,20 +0,0 @@ -package io.nekohasekai.sagernet.utils - -import android.annotation.SuppressLint -import android.annotation.TargetApi -import android.app.Application -import android.content.Context - -@SuppressLint("Registered") -@TargetApi(24) -class DeviceStorageApp(context: Context) : Application() { - init { - attachBaseContext(context.createDeviceProtectedStorageContext()) - } - - /** - * Thou shalt not get the REAL underlying application context which would no longer be operating under device - * protected storage. - */ - override fun getApplicationContext() = this -} diff --git a/app/src/main/java/moe/matsuri/nb4a/NativeInterface.kt b/app/src/main/java/moe/matsuri/nb4a/NativeInterface.kt new file mode 100644 index 0000000..79c4f7e --- /dev/null +++ b/app/src/main/java/moe/matsuri/nb4a/NativeInterface.kt @@ -0,0 +1,96 @@ +package moe.matsuri.nb4a + +import android.os.Build +import androidx.annotation.RequiresApi +import io.nekohasekai.sagernet.SagerNet +import io.nekohasekai.sagernet.bg.ServiceNotification +import io.nekohasekai.sagernet.database.DataStore +import io.nekohasekai.sagernet.database.SagerDatabase +import io.nekohasekai.sagernet.ktx.Logs +import io.nekohasekai.sagernet.ktx.runOnDefaultDispatcher +import io.nekohasekai.sagernet.utils.PackageCache +import libcore.BoxPlatformInterface +import libcore.NB4AInterface +import moe.matsuri.nb4a.utils.LibcoreUtil +import java.net.InetSocketAddress + +class NativeInterface : BoxPlatformInterface, NB4AInterface { + + // libbox interface + + override fun autoDetectInterfaceControl(fd: Int) { + DataStore.vpnService?.protect(fd) + } + + override fun openTun(singTunOptionsJson: String, tunPlatformOptionsJson: String): Long { + if (DataStore.vpnService == null) { + throw Exception("no VpnService") + } + return DataStore.vpnService!!.startVpn(singTunOptionsJson, tunPlatformOptionsJson).toLong() + } + + override fun useProcFS(): Boolean { + return Build.VERSION.SDK_INT < Build.VERSION_CODES.Q + } + + @RequiresApi(Build.VERSION_CODES.Q) + override fun findConnectionOwner( + ipProto: Int, srcIp: String, srcPort: Int, destIp: String, destPort: Int + ): Int { + return SagerNet.connectivity.getConnectionOwnerUid( + ipProto, InetSocketAddress(srcIp, srcPort), InetSocketAddress(destIp, destPort) + ) + } + + override fun packageNameByUid(uid: Int): String { + PackageCache.awaitLoadSync() + + if (uid <= 1000L) { + return "android" + } + + val packageNames = PackageCache.uidMap[uid] + if (!packageNames.isNullOrEmpty()) for (packageName in packageNames) { + return packageName + } + + error("unknown uid $uid") + } + + override fun uidByPackageName(packageName: String): Int { + PackageCache.awaitLoadSync() + return PackageCache[packageName] ?: 0 + } + + // nb4a interface + + override fun useOfficialAssets(): Boolean { + return DataStore.rulesProvider == 0 + } + + override fun selector_OnProxySelected(selectorTag: String, tag: String) { + if (selectorTag != "proxy") { + Logs.d("other selector: $selectorTag") + return + } + LibcoreUtil.resetAllConnections(true) + DataStore.baseService?.apply { + runOnDefaultDispatcher { + val id = data.proxy!!.config.profileTagMap + .filterValues { it == tag }.keys.firstOrNull() ?: -1 + val ent = SagerDatabase.proxyDao.getById(id) ?: return@runOnDefaultDispatcher + // traffic & title + data.proxy?.apply { + looper?.selectMain(id) + displayProfileName = ServiceNotification.genTitle(ent) + data.notification?.postNotificationTitle(displayProfileName) + } + // post binder + data.binder.broadcast { b -> + b.cbSelectorUpdate(id) + } + } + } + } + +} diff --git a/buildScript/lib/core/get_source_env.sh b/buildScript/lib/core/get_source_env.sh index 12d783c..b762f05 100644 --- a/buildScript/lib/core/get_source_env.sh +++ b/buildScript/lib/core/get_source_env.sh @@ -1,5 +1,5 @@ if [ ! -z $ENV_NB4A ]; then - export COMMIT_SING_BOX_EXTRA="9400fd007ad5a19b5892a7c42aae0951e1163747" + export COMMIT_SING_BOX_EXTRA="3805838008319a97e4495f43e10a1d4c9c1e512a" fi if [ ! -z $ENV_SING_BOX_EXTRA ]; then diff --git a/libcore/dns.go b/libcore/dns.go index 5c8b7c0..bf516a8 100644 --- a/libcore/dns.go +++ b/libcore/dns.go @@ -21,13 +21,10 @@ func init() { D.RegisterTransport([]string{"underlying"}, createUnderlyingTransport) } -// CreateUnderlyingTransport for Android func createUnderlyingTransport(name string, ctx context.Context, logger logger.ContextLogger, dialer N.Dialer, link string) (D.Transport, error) { return &androidUnderlyingTransportSing{name, underlyingResolver}, nil } -// - type androidUnderlyingTransportSing struct { name string *androidUnderlyingTransport @@ -37,12 +34,10 @@ func (t *androidUnderlyingTransportSing) Name() string { return t.name } // -var systemResolver = &net.Resolver{PreferGo: false} // Using System API, lookup from current network. -var underlyingResolver = &androidUnderlyingTransport{systemResolver: systemResolver} // Using System API, lookup from non-VPN network. +var systemResolver = &net.Resolver{PreferGo: false} // Using System API, lookup from current network. +var underlyingResolver = &androidUnderlyingTransport{} // Using System API, lookup from non-VPN network. -type androidUnderlyingTransport struct { - systemResolver *net.Resolver -} +type androidUnderlyingTransport struct{} func (t *androidUnderlyingTransport) Start() error { return nil } func (t *androidUnderlyingTransport) Close() error { return nil } @@ -96,7 +91,7 @@ func (t *androidUnderlyingTransport) Lookup(ctx context.Context, domain string, ips = append(ips, netip.MustParseAddr(ip)) } } else { - ips2, err2 := t.systemResolver.LookupIP(context.Background(), network, domain) + ips2, err2 := systemResolver.LookupIP(context.Background(), network, domain) if err2 != nil { err = err2 return diff --git a/libcore/nb4a.go b/libcore/nb4a.go index 9c71e37..d22fbe2 100644 --- a/libcore/nb4a.go +++ b/libcore/nb4a.go @@ -32,19 +32,17 @@ func ForceGc() { go runtime.GC() } -func SetLocalResolver(lr LocalResolver) { - localResolver = lr -} - func InitCore(process, cachePath, internalAssets, externalAssets string, maxLogSizeKb int32, logEnable bool, - iif NB4AInterface, + if1 NB4AInterface, if2 BoxPlatformInterface, ) { defer device.DeferPanicToError("InitCore", func(err error) { log.Println(err) }) isBgProcess := strings.HasSuffix(process, ":bg") neko_common.RunMode = neko_common.RunMode_NekoBoxForAndroid - intfNB4A = iif + intfNB4A = if1 + intfBox = if2 + useProcfs = intfBox.UseProcFS() // Working dir tmp := filepath.Join(cachePath, "../no_backup") @@ -64,7 +62,7 @@ func InitCore(process, cachePath, internalAssets, externalAssets string, boxmain.DisableColor() // nekoutils - nekoutils.Selector_OnProxySelected = iif.Selector_OnProxySelected + nekoutils.Selector_OnProxySelected = intfNB4A.Selector_OnProxySelected // Set up some component go func() { diff --git a/libcore/platform_java.go b/libcore/platform_java.go index 6cae9d6..94ccff1 100644 --- a/libcore/platform_java.go +++ b/libcore/platform_java.go @@ -16,6 +16,10 @@ type LocalResolver interface { var localResolver LocalResolver // Android: passed from java (only when VPNService) +func SetLocalResolver(lr LocalResolver) { + localResolver = lr +} + type BoxPlatformInterface interface { AutoDetectInterfaceControl(fd int32) error OpenTun(singTunOptionsJson, tunPlatformOptionsJson string) (int, error) @@ -24,8 +28,3 @@ type BoxPlatformInterface interface { PackageNameByUid(uid int32) (string, error) UIDByPackageName(packageName string) (int32, error) } - -func SetBoxPlatformInterface(iif BoxPlatformInterface) { - intfBox = iif - useProcfs = intfBox.UseProcFS() -}