Skip to content

Commit 23c5561

Browse files
committed
Fix filtering of V4AndV6 IP properties according to the selected version(s) and inherently optimize its retrieval
1 parent d5ddd90 commit 23c5561

File tree

3 files changed

+69
-39
lines changed

3 files changed

+69
-39
lines changed

app/src/main/kotlin/com/w2sv/wifiwidget/ui/screens/home/components/wifistatus/WifiPropertyDisplay.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ private fun PropertyList(
172172
.padding(bottom = 2.dp)
173173
)
174174
}
175-
items(viewData, key = { it.hashCode() }) { viewData ->
175+
items(viewData) { viewData ->
176176
when (viewData) {
177177
is PropertyListElement.Property -> {
178178
PropertyDisplayRow(

networking/src/main/kotlin/com/w2sv/networking/IPAddress.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ data class IPAddress(
3434
// ".${(shift and 0x000000ff) and 0xff}"
3535
// }
3636

37-
val type: Type = if (prefixLength < Type.V6.minPrefixLength) Type.V4 else Type.V6
38-
val hostAddressRepresentation: String = hostAddress ?: type.fallbackAddress
37+
val version: Version = if (prefixLength < Version.V6.minPrefixLength) Version.V4 else Version.V6
38+
val hostAddressRepresentation: String = hostAddress ?: version.fallbackAddress
3939

4040
private val isLocal: Boolean
4141
get() = isSiteLocal || isLinkLocal || isAnyLocal
@@ -49,7 +49,7 @@ data class IPAddress(
4949
val isGlobalUnicast: Boolean
5050
get() = !isLocal && !isMulticast
5151

52-
enum class Type(
52+
enum class Version(
5353
val minPrefixLength: Int,
5454
val fallbackAddress: String,
5555
val ofCorrectFormat: (String) -> Boolean

networking/src/main/kotlin/com/w2sv/networking/WidgetWifiPropertyViewDataFactoryImpl.kt

Lines changed: 65 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,10 @@ class WidgetWifiPropertyViewDataFactoryImpl @Inject constructor(
7373
WidgetWifiProperty.NonIP.Other.DNS -> {
7474
add(
7575
textualIPv4Representation(wifiManager.dhcpInfo.dns1)
76-
?: IPAddress.Type.V4.fallbackAddress
76+
?: IPAddress.Version.V4.fallbackAddress
7777
)
7878
textualIPv4Representation(wifiManager.dhcpInfo.dns2)?.let { address ->
79-
if (address != IPAddress.Type.V4.fallbackAddress) {
79+
if (address != IPAddress.Version.V4.fallbackAddress) {
8080
add(address)
8181
}
8282
}
@@ -100,12 +100,12 @@ class WidgetWifiPropertyViewDataFactoryImpl @Inject constructor(
100100
WidgetWifiProperty.NonIP.Other.LinkSpeed -> add("${wifiManager.connectionInfo.linkSpeed} Mbps")
101101
WidgetWifiProperty.NonIP.Other.Gateway -> add(
102102
textualIPv4Representation(wifiManager.dhcpInfo.gateway)
103-
?: IPAddress.Type.V4.fallbackAddress
103+
?: IPAddress.Version.V4.fallbackAddress
104104
)
105105

106106
WidgetWifiProperty.NonIP.Other.DHCP -> add(
107107
textualIPv4Representation(wifiManager.dhcpInfo.serverAddress)
108-
?: IPAddress.Type.V4.fallbackAddress
108+
?: IPAddress.Version.V4.fallbackAddress
109109
)
110110
}
111111
}
@@ -115,20 +115,20 @@ class WidgetWifiPropertyViewDataFactoryImpl @Inject constructor(
115115
ipSubProperties: Set<WidgetWifiProperty.IP.SubProperty>
116116
): List<WidgetWifiProperty.ViewData.IPProperty> =
117117
getViewData(
118-
values = getAddresses(systemIPAddresses)
119-
.run {
120-
if (this is WidgetWifiProperty.IP.V4AndV6)
121-
filter {
122-
ipSubProperties.contains(
123-
when (it.type) {
124-
IPAddress.Type.V4 -> v4EnabledSubProperty
125-
IPAddress.Type.V6 -> v6EnabledSubProperty
126-
}
127-
)
118+
values = when (this) {
119+
is WidgetWifiProperty.IP.V6Only -> getAddresses(systemIPAddresses)
120+
is WidgetWifiProperty.IP.V4AndV6 -> getAddresses(
121+
systemIPAddresses = systemIPAddresses,
122+
versionsToBeIncluded = buildSet {
123+
if (ipSubProperties.contains(v4EnabledSubProperty)) {
124+
add(IPAddress.Version.V4)
128125
}
129-
else
130-
this
131-
},
126+
if (ipSubProperties.contains(v6EnabledSubProperty)) {
127+
add(IPAddress.Version.V6)
128+
}
129+
}
130+
)
131+
},
132132
makeViewData = { label, ipAddress ->
133133
WidgetWifiProperty.ViewData.IPProperty(
134134
label = label,
@@ -138,20 +138,39 @@ class WidgetWifiPropertyViewDataFactoryImpl @Inject constructor(
138138
}
139139
)
140140

141-
private suspend fun WidgetWifiProperty.IP.getAddresses(systemIPAddresses: List<IPAddress>): List<IPAddress> =
141+
private fun WidgetWifiProperty.IP.V6Only.getAddresses(systemIPAddresses: List<IPAddress>): List<IPAddress> =
142142
when (this) {
143-
WidgetWifiProperty.IP.V4AndV6.Loopback -> systemIPAddresses.filter { it.isLoopback }
144-
WidgetWifiProperty.IP.V4AndV6.SiteLocal -> systemIPAddresses.filter { it.isSiteLocal }
145-
WidgetWifiProperty.IP.V4AndV6.LinkLocal -> systemIPAddresses.filter { it.isLinkLocal }
146143
WidgetWifiProperty.IP.V6Only.ULA -> systemIPAddresses.filter { it.isUniqueLocal }
147-
WidgetWifiProperty.IP.V4AndV6.Multicast -> systemIPAddresses.filter { it.isMulticast }
148144
WidgetWifiProperty.IP.V6Only.GUA -> systemIPAddresses.filter { it.isGlobalUnicast }
145+
}
146+
147+
private suspend fun WidgetWifiProperty.IP.V4AndV6.getAddresses(
148+
systemIPAddresses: List<IPAddress>,
149+
versionsToBeIncluded: Set<IPAddress.Version>
150+
): List<IPAddress> =
151+
when (this) {
152+
WidgetWifiProperty.IP.V4AndV6.Loopback -> systemIPAddresses.filterByVersionAnd(
153+
versionsToBeIncluded
154+
) { it.isLoopback }
155+
156+
WidgetWifiProperty.IP.V4AndV6.SiteLocal -> systemIPAddresses.filterByVersionAnd(
157+
versionsToBeIncluded
158+
) { it.isSiteLocal }
159+
160+
WidgetWifiProperty.IP.V4AndV6.LinkLocal -> systemIPAddresses.filterByVersionAnd(
161+
versionsToBeIncluded
162+
) { it.isLinkLocal }
163+
164+
WidgetWifiProperty.IP.V4AndV6.Multicast -> systemIPAddresses.filterByVersionAnd(
165+
versionsToBeIncluded
166+
) { it.isMulticast }
167+
149168
WidgetWifiProperty.IP.V4AndV6.Public -> buildList {
150-
IPAddress.Type.entries.forEach { type ->
151-
getPublicIPAddress(httpClient, type)?.let { addressRepresentation ->
169+
versionsToBeIncluded.forEach { version ->
170+
getPublicIPAddress(httpClient, version)?.let { addressRepresentation ->
152171
add(
153172
IPAddress(
154-
prefixLength = type.minPrefixLength,
173+
prefixLength = version.minPrefixLength,
155174
hostAddress = addressRepresentation,
156175
isLinkLocal = false,
157176
isSiteLocal = false,
@@ -189,6 +208,12 @@ class WidgetWifiPropertyViewDataFactoryImpl @Inject constructor(
189208
}
190209
}
191210

211+
private inline fun List<IPAddress>.filterByVersionAnd(
212+
versionsToBeIncluded: Set<IPAddress.Version>,
213+
predicate: (IPAddress) -> Boolean
214+
): List<IPAddress> =
215+
filter { predicate(it) && versionsToBeIncluded.contains(it.version) }
216+
192217
/**
193218
* Reference: https://stackoverflow.com/a/52663352/12083276
194219
*/
@@ -202,36 +227,41 @@ private fun textualIPv4Representation(address: Int): String? =
202227
)
203228
.hostAddress
204229

205-
private suspend fun getPublicIPAddress(httpClient: OkHttpClient, type: IPAddress.Type): String? {
206-
i { "Getting public $type address" }
230+
private const val PUBLIC_IP_ADDRESS_RETRIEVAL_TIMEOUT = 5_000L
231+
232+
private suspend fun getPublicIPAddress(
233+
httpClient: OkHttpClient,
234+
version: IPAddress.Version
235+
): String? {
236+
i { "Getting public $version address" }
207237

208238
val request = Request.Builder()
209239
.url(
210-
when (type) {
211-
IPAddress.Type.V4 -> "https://api.ipify.org"
212-
IPAddress.Type.V6 -> "https://api64.ipify.org"
240+
when (version) {
241+
IPAddress.Version.V4 -> "https://api.ipify.org"
242+
IPAddress.Version.V6 -> "https://api6.ipify.org"
213243
}
214244
)
215245
.build()
216246

217247
return try {
218-
withTimeout(5_000) {
248+
withTimeout(PUBLIC_IP_ADDRESS_RETRIEVAL_TIMEOUT) {
219249
httpClient
220250
.newCall(request)
221251
.execute()
222252
.body
223253
?.string()
224254
?.let { address ->
225-
if (type.ofCorrectFormat(address))
226-
address.also { i { "Got public $type address" } }
255+
if (version.ofCorrectFormat(address))
256+
address.also { i { "Got public $version address" } }
227257
else
228-
null.also { i { "Discarded obtained $type address $address due to incorrect format" } }
258+
null.also { i { "Discarded obtained $version address $address due to incorrect format" } }
229259
}
230260
}
231261
} catch (e: Exception) {
232262
i {
233263
if (e is SocketTimeoutException) {
234-
"Timed out trying to get public $type address"
264+
"Timed out trying to get public $version address"
235265
} else {
236266
"Caught $e"
237267
}

0 commit comments

Comments
 (0)