Skip to content

Commit 87c9f1b

Browse files
committed
Implement new interface api
1 parent 72e3014 commit 87c9f1b

File tree

2 files changed

+91
-55
lines changed

2 files changed

+91
-55
lines changed

app/src/main/java/io/nekohasekai/sfa/bg/DefaultNetworkMonitor.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,19 +63,19 @@ object DefaultNetworkMonitor {
6363
// https://github.com/golang/go/issues/68760
6464
if (BuildConfig.DEBUG) {
6565
GlobalScope.launch(Dispatchers.IO) {
66-
listener.updateDefaultInterface(interfaceName, interfaceIndex)
66+
listener.updateDefaultInterface(interfaceName, interfaceIndex, false, false)
6767
}
6868
} else {
69-
listener.updateDefaultInterface(interfaceName, interfaceIndex)
69+
listener.updateDefaultInterface(interfaceName, interfaceIndex, false, false)
7070
}
7171
}
7272
} else {
7373
if (BuildConfig.DEBUG) {
7474
GlobalScope.launch(Dispatchers.IO) {
75-
listener.updateDefaultInterface("", -1)
75+
listener.updateDefaultInterface("", -1, false, false)
7676
}
7777
} else {
78-
listener.updateDefaultInterface("", -1)
78+
listener.updateDefaultInterface("", -1, false, false)
7979
}
8080
}
8181
}

app/src/main/java/io/nekohasekai/sfa/bg/PlatformInterfaceWrapper.kt

Lines changed: 87 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,14 @@ package io.nekohasekai.sfa.bg
22

33
import android.annotation.SuppressLint
44
import android.content.pm.PackageManager
5+
import android.net.NetworkCapabilities
56
import android.os.Build
67
import android.os.Process
8+
import android.system.OsConstants
9+
import android.util.Log
710
import androidx.annotation.RequiresApi
811
import io.nekohasekai.libbox.InterfaceUpdateListener
12+
import io.nekohasekai.libbox.Libbox
913
import io.nekohasekai.libbox.NetworkInterfaceIterator
1014
import io.nekohasekai.libbox.PlatformInterface
1115
import io.nekohasekai.libbox.StringIterator
@@ -16,7 +20,6 @@ import java.net.Inet6Address
1620
import java.net.InetSocketAddress
1721
import java.net.InterfaceAddress
1822
import java.net.NetworkInterface
19-
import java.util.Enumeration
2023
import io.nekohasekai.libbox.NetworkInterface as LibboxNetworkInterface
2124

2225
interface PlatformInterfaceWrapper : PlatformInterface {
@@ -44,13 +47,19 @@ interface PlatformInterfaceWrapper : PlatformInterface {
4447
destinationAddress: String,
4548
destinationPort: Int
4649
): Int {
47-
val uid = Application.connectivity.getConnectionOwnerUid(
48-
ipProtocol,
49-
InetSocketAddress(sourceAddress, sourcePort),
50-
InetSocketAddress(destinationAddress, destinationPort)
51-
)
52-
if (uid == Process.INVALID_UID) error("android: connection owner not found")
53-
return uid
50+
try {
51+
val uid = Application.connectivity.getConnectionOwnerUid(
52+
ipProtocol,
53+
InetSocketAddress(sourceAddress, sourcePort),
54+
InetSocketAddress(destinationAddress, destinationPort)
55+
)
56+
if (uid == Process.INVALID_UID) error("android: connection owner not found")
57+
return uid
58+
} catch (e: Exception) {
59+
Log.e("PlatformInterface", "getConnectionOwnerUid", e)
60+
e.printStackTrace(System.err)
61+
throw e
62+
}
5463
}
5564

5665
override fun packageNameByUid(uid: Int): String {
@@ -76,10 +85,6 @@ interface PlatformInterfaceWrapper : PlatformInterface {
7685
}
7786
}
7887

79-
override fun usePlatformDefaultInterfaceMonitor(): Boolean {
80-
return true
81-
}
82-
8388
override fun startDefaultInterfaceMonitor(listener: InterfaceUpdateListener) {
8489
DefaultNetworkMonitor.setListener(listener)
8590
}
@@ -88,12 +93,56 @@ interface PlatformInterfaceWrapper : PlatformInterface {
8893
DefaultNetworkMonitor.setListener(null)
8994
}
9095

91-
override fun usePlatformInterfaceGetter(): Boolean {
92-
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
93-
}
94-
9596
override fun getInterfaces(): NetworkInterfaceIterator {
96-
return InterfaceArray(NetworkInterface.getNetworkInterfaces())
97+
val networks = Application.connectivity.allNetworks
98+
val networkInterfaces = NetworkInterface.getNetworkInterfaces().toList()
99+
val interfaces = mutableListOf<LibboxNetworkInterface>()
100+
for (network in networks) {
101+
val boxInterface = LibboxNetworkInterface()
102+
val linkProperties = Application.connectivity.getLinkProperties(network) ?: continue
103+
val networkCapabilities =
104+
Application.connectivity.getNetworkCapabilities(network) ?: continue
105+
boxInterface.name = linkProperties.interfaceName
106+
val networkInterface =
107+
networkInterfaces.find { it.name == boxInterface.name } ?: continue
108+
boxInterface.dnsServer =
109+
StringArray(linkProperties.dnsServers.mapNotNull { it.hostAddress }.iterator())
110+
boxInterface.type = when {
111+
networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> Libbox.InterfaceTypeWIFI
112+
networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> Libbox.InterfaceTypeCellular
113+
networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> Libbox.InterfaceTypeEthernet
114+
else -> Libbox.InterfaceTypeOther
115+
}
116+
boxInterface.index = networkInterface.index
117+
runCatching {
118+
boxInterface.mtu = networkInterface.mtu
119+
}.onFailure {
120+
Log.e(
121+
"PlatformInterface", "failed to get mtu for interface ${boxInterface.name}", it
122+
)
123+
}
124+
boxInterface.addresses =
125+
StringArray(networkInterface.interfaceAddresses.mapTo(mutableListOf()) { it.toPrefix() }
126+
.iterator())
127+
var dumpFlags = 0
128+
if (networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
129+
dumpFlags = OsConstants.IFF_UP or OsConstants.IFF_RUNNING
130+
}
131+
if (networkInterface.isLoopback) {
132+
dumpFlags = dumpFlags or OsConstants.IFF_LOOPBACK
133+
}
134+
if (networkInterface.isPointToPoint) {
135+
dumpFlags = dumpFlags or OsConstants.IFF_POINTOPOINT
136+
}
137+
if (networkInterface.supportsMulticast()) {
138+
dumpFlags = dumpFlags or OsConstants.IFF_MULTICAST
139+
}
140+
boxInterface.flags = dumpFlags
141+
boxInterface.metered =
142+
!networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
143+
interfaces.add(boxInterface)
144+
}
145+
return InterfaceArray(interfaces.iterator())
97146
}
98147

99148
override fun underNetworkExtension(): Boolean {
@@ -108,55 +157,29 @@ interface PlatformInterfaceWrapper : PlatformInterface {
108157
}
109158

110159
override fun readWIFIState(): WIFIState? {
111-
@Suppress("DEPRECATION")
112-
val wifiInfo = Application.wifiManager.connectionInfo ?: return null
160+
@Suppress("DEPRECATION") val wifiInfo =
161+
Application.wifiManager.connectionInfo ?: return null
113162
var ssid = wifiInfo.ssid
163+
if (ssid == "<unknown ssid>") {
164+
return WIFIState("", "")
165+
}
114166
if (ssid.startsWith("\"") && ssid.endsWith("\"")) {
115167
ssid = ssid.substring(1, ssid.length - 1)
116168
}
117169
return WIFIState(ssid, wifiInfo.bssid)
118170
}
119171

120-
private class InterfaceArray(private val iterator: Enumeration<NetworkInterface>) :
172+
private class InterfaceArray(private val iterator: Iterator<LibboxNetworkInterface>) :
121173
NetworkInterfaceIterator {
122174

123175
override fun hasNext(): Boolean {
124-
return iterator.hasMoreElements()
176+
return iterator.hasNext()
125177
}
126178

127179
override fun next(): LibboxNetworkInterface {
128-
val element = iterator.nextElement()
129-
return LibboxNetworkInterface().apply {
130-
name = element.name
131-
index = element.index
132-
runCatching {
133-
mtu = element.mtu
134-
}
135-
addresses =
136-
StringArray(
137-
element.interfaceAddresses.mapTo(mutableListOf()) { it.toPrefix() }
138-
.iterator()
139-
)
140-
runCatching {
141-
flags = element.flags
142-
}
143-
}
144-
}
145-
146-
private fun InterfaceAddress.toPrefix(): String {
147-
return if (address is Inet6Address) {
148-
"${Inet6Address.getByAddress(address.address).hostAddress}/${networkPrefixLength}"
149-
} else {
150-
"${address.hostAddress}/${networkPrefixLength}"
151-
}
180+
return iterator.next()
152181
}
153182

154-
private val NetworkInterface.flags: Int
155-
@SuppressLint("SoonBlockedPrivateApi")
156-
get() {
157-
val getFlagsMethod = NetworkInterface::class.java.getDeclaredMethod("getFlags")
158-
return getFlagsMethod.invoke(this) as Int
159-
}
160183
}
161184

162185
private class StringArray(private val iterator: Iterator<String>) : StringIterator {
@@ -175,4 +198,17 @@ interface PlatformInterfaceWrapper : PlatformInterface {
175198
}
176199
}
177200

201+
private fun InterfaceAddress.toPrefix(): String {
202+
return if (address is Inet6Address) {
203+
"${Inet6Address.getByAddress(address.address).hostAddress}/${networkPrefixLength}"
204+
} else {
205+
"${address.hostAddress}/${networkPrefixLength}"
206+
}
207+
}
208+
209+
private val NetworkInterface.flags: Int
210+
@SuppressLint("SoonBlockedPrivateApi") get() {
211+
val getFlagsMethod = NetworkInterface::class.java.getDeclaredMethod("getFlags")
212+
return getFlagsMethod.invoke(this) as Int
213+
}
178214
}

0 commit comments

Comments
 (0)