Implement new interface api

This commit is contained in:
世界 2024-11-13 10:44:56 +08:00
parent cff12c57dd
commit e0f8b4fe56
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
2 changed files with 89 additions and 53 deletions

View file

@ -55,10 +55,10 @@ object DefaultNetworkMonitor {
Thread.sleep(100) Thread.sleep(100)
continue continue
} }
listener.updateDefaultInterface(interfaceName, interfaceIndex) listener.updateDefaultInterface(interfaceName, interfaceIndex, false, false)
} }
} else { } else {
listener.updateDefaultInterface("", -1) listener.updateDefaultInterface("", -1, false, false)
} }
} }

View file

@ -2,10 +2,14 @@ package io.nekohasekai.sfa.bg
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.net.NetworkCapabilities
import android.os.Build import android.os.Build
import android.os.Process import android.os.Process
import android.system.OsConstants
import android.util.Log
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import io.nekohasekai.libbox.InterfaceUpdateListener import io.nekohasekai.libbox.InterfaceUpdateListener
import io.nekohasekai.libbox.Libbox
import io.nekohasekai.libbox.NetworkInterfaceIterator import io.nekohasekai.libbox.NetworkInterfaceIterator
import io.nekohasekai.libbox.PlatformInterface import io.nekohasekai.libbox.PlatformInterface
import io.nekohasekai.libbox.StringIterator import io.nekohasekai.libbox.StringIterator
@ -16,7 +20,6 @@ import java.net.Inet6Address
import java.net.InetSocketAddress import java.net.InetSocketAddress
import java.net.InterfaceAddress import java.net.InterfaceAddress
import java.net.NetworkInterface import java.net.NetworkInterface
import java.util.Enumeration
import io.nekohasekai.libbox.NetworkInterface as LibboxNetworkInterface import io.nekohasekai.libbox.NetworkInterface as LibboxNetworkInterface
interface PlatformInterfaceWrapper : PlatformInterface { interface PlatformInterfaceWrapper : PlatformInterface {
@ -44,6 +47,7 @@ interface PlatformInterfaceWrapper : PlatformInterface {
destinationAddress: String, destinationAddress: String,
destinationPort: Int destinationPort: Int
): Int { ): Int {
try {
val uid = Application.connectivity.getConnectionOwnerUid( val uid = Application.connectivity.getConnectionOwnerUid(
ipProtocol, ipProtocol,
InetSocketAddress(sourceAddress, sourcePort), InetSocketAddress(sourceAddress, sourcePort),
@ -51,6 +55,11 @@ interface PlatformInterfaceWrapper : PlatformInterface {
) )
if (uid == Process.INVALID_UID) error("android: connection owner not found") if (uid == Process.INVALID_UID) error("android: connection owner not found")
return uid return uid
} catch (e: Exception) {
Log.e("PlatformInterface", "getConnectionOwnerUid", e)
e.printStackTrace(System.err)
throw e
}
} }
override fun packageNameByUid(uid: Int): String { override fun packageNameByUid(uid: Int): String {
@ -76,10 +85,6 @@ interface PlatformInterfaceWrapper : PlatformInterface {
} }
} }
override fun usePlatformDefaultInterfaceMonitor(): Boolean {
return true
}
override fun startDefaultInterfaceMonitor(listener: InterfaceUpdateListener) { override fun startDefaultInterfaceMonitor(listener: InterfaceUpdateListener) {
DefaultNetworkMonitor.setListener(listener) DefaultNetworkMonitor.setListener(listener)
} }
@ -88,12 +93,56 @@ interface PlatformInterfaceWrapper : PlatformInterface {
DefaultNetworkMonitor.setListener(null) DefaultNetworkMonitor.setListener(null)
} }
override fun usePlatformInterfaceGetter(): Boolean {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
}
override fun getInterfaces(): NetworkInterfaceIterator { override fun getInterfaces(): NetworkInterfaceIterator {
return InterfaceArray(NetworkInterface.getNetworkInterfaces()) val networks = Application.connectivity.allNetworks
val networkInterfaces = NetworkInterface.getNetworkInterfaces().toList()
val interfaces = mutableListOf<LibboxNetworkInterface>()
for (network in networks) {
val boxInterface = LibboxNetworkInterface()
val linkProperties = Application.connectivity.getLinkProperties(network) ?: continue
val networkCapabilities =
Application.connectivity.getNetworkCapabilities(network) ?: continue
boxInterface.name = linkProperties.interfaceName
val networkInterface =
networkInterfaces.find { it.name == boxInterface.name } ?: continue
boxInterface.dnsServer =
StringArray(linkProperties.dnsServers.mapNotNull { it.hostAddress }.iterator())
boxInterface.type = when {
networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> Libbox.InterfaceTypeWIFI
networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> Libbox.InterfaceTypeCellular
networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> Libbox.InterfaceTypeEthernet
else -> Libbox.InterfaceTypeOther
}
boxInterface.index = networkInterface.index
runCatching {
boxInterface.mtu = networkInterface.mtu
}.onFailure {
Log.e(
"PlatformInterface", "failed to get mtu for interface ${boxInterface.name}", it
)
}
boxInterface.addresses =
StringArray(networkInterface.interfaceAddresses.mapTo(mutableListOf()) { it.toPrefix() }
.iterator())
var dumpFlags = 0
if (networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
dumpFlags = OsConstants.IFF_UP or OsConstants.IFF_RUNNING
}
if (networkInterface.isLoopback) {
dumpFlags = dumpFlags or OsConstants.IFF_LOOPBACK
}
if (networkInterface.isPointToPoint) {
dumpFlags = dumpFlags or OsConstants.IFF_POINTOPOINT
}
if (networkInterface.supportsMulticast()) {
dumpFlags = dumpFlags or OsConstants.IFF_MULTICAST
}
boxInterface.flags = dumpFlags
boxInterface.metered =
!networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
interfaces.add(boxInterface)
}
return InterfaceArray(interfaces.iterator())
} }
override fun underNetworkExtension(): Boolean { override fun underNetworkExtension(): Boolean {
@ -108,55 +157,29 @@ interface PlatformInterfaceWrapper : PlatformInterface {
} }
override fun readWIFIState(): WIFIState? { override fun readWIFIState(): WIFIState? {
@Suppress("DEPRECATION") @Suppress("DEPRECATION") val wifiInfo =
val wifiInfo = Application.wifiManager.connectionInfo ?: return null Application.wifiManager.connectionInfo ?: return null
var ssid = wifiInfo.ssid var ssid = wifiInfo.ssid
if (ssid == "<unknown ssid>") {
return WIFIState("", "")
}
if (ssid.startsWith("\"") && ssid.endsWith("\"")) { if (ssid.startsWith("\"") && ssid.endsWith("\"")) {
ssid = ssid.substring(1, ssid.length - 1) ssid = ssid.substring(1, ssid.length - 1)
} }
return WIFIState(ssid, wifiInfo.bssid) return WIFIState(ssid, wifiInfo.bssid)
} }
private class InterfaceArray(private val iterator: Enumeration<NetworkInterface>) : private class InterfaceArray(private val iterator: Iterator<LibboxNetworkInterface>) :
NetworkInterfaceIterator { NetworkInterfaceIterator {
override fun hasNext(): Boolean { override fun hasNext(): Boolean {
return iterator.hasMoreElements() return iterator.hasNext()
} }
override fun next(): LibboxNetworkInterface { override fun next(): LibboxNetworkInterface {
val element = iterator.nextElement() return iterator.next()
return LibboxNetworkInterface().apply {
name = element.name
index = element.index
runCatching {
mtu = element.mtu
}
addresses =
StringArray(
element.interfaceAddresses.mapTo(mutableListOf()) { it.toPrefix() }
.iterator()
)
runCatching {
flags = element.flags
}
}
} }
private fun InterfaceAddress.toPrefix(): String {
return if (address is Inet6Address) {
"${Inet6Address.getByAddress(address.address).hostAddress}/${networkPrefixLength}"
} else {
"${address.hostAddress}/${networkPrefixLength}"
}
}
private val NetworkInterface.flags: Int
@SuppressLint("SoonBlockedPrivateApi")
get() {
val getFlagsMethod = NetworkInterface::class.java.getDeclaredMethod("getFlags")
return getFlagsMethod.invoke(this) as Int
}
} }
private class StringArray(private val iterator: Iterator<String>) : StringIterator { private class StringArray(private val iterator: Iterator<String>) : StringIterator {
@ -175,4 +198,17 @@ interface PlatformInterfaceWrapper : PlatformInterface {
} }
} }
private fun InterfaceAddress.toPrefix(): String {
return if (address is Inet6Address) {
"${Inet6Address.getByAddress(address.address).hostAddress}/${networkPrefixLength}"
} else {
"${address.hostAddress}/${networkPrefixLength}"
}
}
private val NetworkInterface.flags: Int
@SuppressLint("SoonBlockedPrivateApi") get() {
val getFlagsMethod = NetworkInterface::class.java.getDeclaredMethod("getFlags")
return getFlagsMethod.invoke(this) as Int
}
} }