Skip to content

Commit cee7b9f

Browse files
Merge pull request #1770 from nextcloud/bugfix/dns-cache-blocking-thread
BugFix - DNSCache Lock
2 parents 89ddcfc + 97125f6 commit cee7b9f

File tree

1 file changed

+20
-18
lines changed

1 file changed

+20
-18
lines changed

library/src/main/java/com/nextcloud/common/DNSCache.kt

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22
* Nextcloud Android Library
33
*
44
* SPDX-FileCopyrightText: 2022-2024 Nextcloud GmbH and Nextcloud contributors
5+
* SPDX-FileCopyrightText: 2025 Alper Ozturk <[email protected]>
56
* SPDX-FileCopyrightText: 2022 Álvaro Brey <[email protected]>
67
* SPDX-License-Identifier: MIT
78
*/
89
package com.nextcloud.common
910

11+
import android.os.Build
1012
import androidx.annotation.VisibleForTesting
1113
import com.nextcloud.android.lib.core.Clock
1214
import com.nextcloud.android.lib.core.ClockImpl
@@ -15,6 +17,7 @@ import java.net.Inet4Address
1517
import java.net.Inet6Address
1618
import java.net.InetAddress
1719
import java.net.UnknownHostException
20+
import java.util.concurrent.ConcurrentHashMap
1821

1922
/**
2023
* DNS Cache which prefers IPv6 unless otherwise specified
@@ -24,12 +27,15 @@ object DNSCache {
2427

2528
// 30 seconds is the Java default. Let's keep it.
2629
@VisibleForTesting
30+
@Volatile
2731
var ttlMillis: Long = DEFAULT_TTL
2832

2933
@VisibleForTesting
34+
@Volatile
3035
var clock: Clock = ClockImpl()
3136

3237
@VisibleForTesting
38+
@Volatile
3339
var dns: Dns = Dns.SYSTEM
3440

3541
data class DNSInfo(
@@ -40,49 +46,47 @@ object DNSCache {
4046
fun isExpired(): Boolean = clock.currentTimeMillis - timestamp > ttlMillis
4147
}
4248

43-
private val cache: MutableMap<String, DNSInfo> = HashMap()
49+
private val cache: ConcurrentHashMap<String, DNSInfo> = ConcurrentHashMap()
4450

4551
@Throws(UnknownHostException::class)
46-
@Synchronized
4752
@JvmStatic
4853
fun lookup(hostname: String): List<InetAddress> {
4954
val entry = cache[hostname]
5055
if (entry?.addresses?.isNotEmpty() == true && !entry.isExpired()) {
5156
return entry.addresses
5257
}
53-
val preferIPV4 =
54-
when (entry) {
55-
null -> false
56-
else -> entry.preferIPV4
57-
}
5858

5959
val addresses = dns.lookup(hostname).toMutableList()
6060
if (addresses.isEmpty()) {
6161
throw UnknownHostException("Unknown host $hostname")
6262
}
63-
val sortedAddresses = sortAddresses(addresses, preferIPV4)
6463

65-
val newEntry = DNSInfo(sortedAddresses, preferIPV4)
66-
cache[hostname] = newEntry
64+
val preferIPV4 = entry?.preferIPV4 ?: false
65+
val sortedAddresses = sortAddresses(addresses, preferIPV4)
66+
cache[hostname] = DNSInfo(sortedAddresses, preferIPV4)
6767

6868
return sortedAddresses
6969
}
7070

7171
/**
7272
* Set IP version preference for a hostname, and re-sort addresses if needed
7373
*/
74-
@Synchronized
7574
@JvmStatic
7675
fun setIPVersionPreference(
7776
hostname: String,
7877
preferIPV4: Boolean
7978
) {
80-
val entry = cache[hostname]
81-
if (entry != null) {
82-
val addresses = sortAddresses(entry.addresses, preferIPV4)
83-
cache[hostname] = DNSInfo(addresses, preferIPV4)
79+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
80+
cache.compute(hostname) { _, old ->
81+
val addresses =
82+
old?.addresses?.let {
83+
sortAddresses(it, preferIPV4)
84+
} ?: emptyList()
85+
DNSInfo(addresses, preferIPV4)
86+
}
8487
} else {
85-
cache[hostname] = DNSInfo(emptyList(), preferIPV4)
88+
val addresses = cache[hostname]?.addresses?.let { sortAddresses(it, preferIPV4) } ?: emptyList()
89+
cache[hostname] = DNSInfo(addresses, preferIPV4)
8690
}
8791
}
8892

@@ -92,7 +96,6 @@ object DNSCache {
9296
* - The first address is an IPv6 address
9397
* - There are IPv4 addresses available too
9498
*/
95-
@Synchronized
9699
@JvmStatic
97100
fun isIPV6First(hostname: String): Boolean {
98101
val firstV6 = cache[hostname]?.addresses?.firstOrNull() is Inet6Address
@@ -103,7 +106,6 @@ object DNSCache {
103106
/**
104107
* Clears the cache
105108
*/
106-
@Synchronized
107109
@JvmStatic
108110
fun clear() {
109111
cache.clear()

0 commit comments

Comments
 (0)