diff --git a/app/src/full/java/com/celzero/bravedns/customdownloader/LocalBlocklistCoordinator.kt b/app/src/full/java/com/celzero/bravedns/customdownloader/LocalBlocklistCoordinator.kt index 777c7795d..17726ad1a 100644 --- a/app/src/full/java/com/celzero/bravedns/customdownloader/LocalBlocklistCoordinator.kt +++ b/app/src/full/java/com/celzero/bravedns/customdownloader/LocalBlocklistCoordinator.kt @@ -34,7 +34,7 @@ import com.celzero.bravedns.data.AppConfig import com.celzero.bravedns.download.BlocklistDownloadHelper import com.celzero.bravedns.service.PersistentState import com.celzero.bravedns.service.RethinkBlocklistManager -import com.celzero.bravedns.ui.activity.HomeScreenActivity +import com.celzero.bravedns.ui.HomeScreenActivity import com.celzero.bravedns.util.Constants import com.celzero.bravedns.util.Constants.Companion.INIT_TIME_MS import com.celzero.bravedns.util.Constants.Companion.LOCAL_BLOCKLIST_DOWNLOAD_FOLDER_NAME @@ -42,11 +42,9 @@ import com.celzero.bravedns.util.LoggerConstants.Companion.LOG_TAG_DOWNLOAD import com.celzero.bravedns.util.UIUtils import com.celzero.bravedns.util.Utilities import com.celzero.bravedns.util.Utilities.blocklistDownloadBasePath +import com.celzero.bravedns.util.Utilities.calculateMd5 +import com.celzero.bravedns.util.Utilities.getTagValueFromJson import com.celzero.bravedns.util.Utilities.tempDownloadBasePath -import dnsx.Dnsx -import okhttp3.ResponseBody -import org.koin.core.component.KoinComponent -import org.koin.core.component.inject import java.io.BufferedInputStream import java.io.File import java.io.FileOutputStream @@ -55,6 +53,9 @@ import java.io.InputStream import java.io.OutputStream import java.util.concurrent.CancellationException import java.util.concurrent.TimeUnit +import okhttp3.ResponseBody +import org.koin.core.component.KoinComponent +import org.koin.core.component.inject class LocalBlocklistCoordinator(val context: Context, workerParams: WorkerParameters) : CoroutineWorker(context, workerParams), KoinComponent { @@ -223,7 +224,7 @@ class LocalBlocklistCoordinator(val context: Context, workerParams: WorkerParame // create okhttp client with base url val retrofit = - getBlocklistBaseBuilder(RetrofitManager.Companion.OkHttpDnsType.DEFAULT) + getBlocklistBaseBuilder(RetrofitManager.Companion.OkHttpDnsType.FALLBACK_DNS) .build() .create(IBlocklistDownload::class.java) val response = retrofit.downloadLocalBlocklistFile(url, persistentState.appVersion, "") @@ -356,16 +357,20 @@ class LocalBlocklistCoordinator(val context: Context, workerParams: WorkerParame try { val path: String = blocklistDownloadBasePath(context, LOCAL_BLOCKLIST_DOWNLOAD_FOLDER_NAME, timestamp) - val braveDNS = - Dnsx.newBraveDNSLocal( - path + Constants.ONDEVICE_BLOCKLIST_FILE_TD, - path + Constants.ONDEVICE_BLOCKLIST_FILE_RD, - path + Constants.ONDEVICE_BLOCKLIST_FILE_BASIC_CONFIG, - path + Constants.ONDEVICE_BLOCKLIST_FILE_TAG - ) + val tdmd5 = calculateMd5(path + Constants.ONDEVICE_BLOCKLIST_FILE_TD) + val rdmd5 = calculateMd5(path + Constants.ONDEVICE_BLOCKLIST_FILE_RD) + val remoteTdmd5 = + getTagValueFromJson(path + Constants.ONDEVICE_BLOCKLIST_FILE_BASIC_CONFIG, "tdmd5") + val remoteRdmd5 = + getTagValueFromJson(path + Constants.ONDEVICE_BLOCKLIST_FILE_BASIC_CONFIG, "rdmd5") if (DEBUG) - Log.d(LOG_TAG_DOWNLOAD, "AppDownloadManager isDownloadValid? ${braveDNS != null}") - return braveDNS != null + Log.d( + LOG_TAG_DOWNLOAD, + "tdmd5: $tdmd5, rdmd5: $rdmd5, remotetd: $remoteTdmd5, remoterd: $remoteRdmd5" + ) + val isDownloadValid = tdmd5 == remoteTdmd5 && rdmd5 == remoteRdmd5 + Log.i(LOG_TAG_DOWNLOAD, "AppDownloadManager isDownloadValid? $isDownloadValid") + return isDownloadValid } catch (e: Exception) { Log.e(LOG_TAG_DOWNLOAD, "AppDownloadManager isDownloadValid exception: ${e.message}", e) } @@ -512,8 +517,6 @@ class LocalBlocklistCoordinator(val context: Context, workerParams: WorkerParame } private fun updatePersistenceOnCopySuccess(timestamp: Long) { - // recreate bravedns object () - appConfig.recreateBraveDnsObj() persistentState.localBlocklistTimestamp = timestamp persistentState.blocklistEnabled = true // reset updatable time stamp diff --git a/app/src/full/java/com/celzero/bravedns/customdownloader/RemoteBlocklistCoordinator.kt b/app/src/full/java/com/celzero/bravedns/customdownloader/RemoteBlocklistCoordinator.kt index a992888dc..6822983f3 100644 --- a/app/src/full/java/com/celzero/bravedns/customdownloader/RemoteBlocklistCoordinator.kt +++ b/app/src/full/java/com/celzero/bravedns/customdownloader/RemoteBlocklistCoordinator.kt @@ -93,7 +93,7 @@ class RemoteBlocklistCoordinator(val context: Context, workerParams: WorkerParam Log.i(LoggerConstants.LOG_TAG_DOWNLOAD, "Download remote blocklist: $timestamp") val retrofit = - RetrofitManager.getBlocklistBaseBuilder(RetrofitManager.Companion.OkHttpDnsType.DEFAULT) + RetrofitManager.getBlocklistBaseBuilder(RetrofitManager.Companion.OkHttpDnsType.FALLBACK_DNS) .addConverterFactory(GsonConverterFactory.create()) .build() val retrofitInterface = retrofit.create(IBlocklistDownload::class.java) diff --git a/app/src/full/java/com/celzero/bravedns/download/FileHandleWorker.kt b/app/src/full/java/com/celzero/bravedns/download/FileHandleWorker.kt index 937a998dd..b0757e2b3 100644 --- a/app/src/full/java/com/celzero/bravedns/download/FileHandleWorker.kt +++ b/app/src/full/java/com/celzero/bravedns/download/FileHandleWorker.kt @@ -29,15 +29,16 @@ import com.celzero.bravedns.util.Constants.Companion.INIT_TIME_MS import com.celzero.bravedns.util.Constants.Companion.LOCAL_BLOCKLIST_DOWNLOAD_FOLDER_NAME import com.celzero.bravedns.util.LoggerConstants.Companion.LOG_TAG_DOWNLOAD import com.celzero.bravedns.util.Utilities +import com.celzero.bravedns.util.Utilities.calculateMd5 +import com.celzero.bravedns.util.Utilities.getTagValueFromJson import com.celzero.bravedns.util.Utilities.hasLocalBlocklists import com.celzero.bravedns.util.Utilities.localBlocklistFileDownloadPath -import dnsx.Dnsx +import java.io.File import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import org.koin.core.component.KoinComponent import org.koin.core.component.inject -import java.io.File /** * Class responsible for copying the files from External path to canonical path. The worker will be @@ -177,26 +178,26 @@ class FileHandleWorker(val context: Context, workerParameters: WorkerParameters) LOCAL_BLOCKLIST_DOWNLOAD_FOLDER_NAME, timestamp ) - val braveDNS = - Dnsx.newBraveDNSLocal( - path + Constants.ONDEVICE_BLOCKLIST_FILE_TD, - path + Constants.ONDEVICE_BLOCKLIST_FILE_RD, - path + Constants.ONDEVICE_BLOCKLIST_FILE_BASIC_CONFIG, - path + Constants.ONDEVICE_BLOCKLIST_FILE_TAG - ) + val tdmd5 = calculateMd5(path + Constants.ONDEVICE_BLOCKLIST_FILE_TD) + val rdmd5 = calculateMd5(path + Constants.ONDEVICE_BLOCKLIST_FILE_RD) + val remoteTdmd5 = + getTagValueFromJson(path + Constants.ONDEVICE_BLOCKLIST_FILE_BASIC_CONFIG, "tdmd5") + val remoteRdmd5 = + getTagValueFromJson(path + Constants.ONDEVICE_BLOCKLIST_FILE_BASIC_CONFIG, "rdmd5") if (DEBUG) - Log.d(LOG_TAG_DOWNLOAD, "AppDownloadManager isDownloadValid? ${braveDNS != null}") - return braveDNS != null + Log.d( + LOG_TAG_DOWNLOAD, + "tdmd5: $tdmd5, rdmd5: $rdmd5, remotetd: $remoteTdmd5, remoterd: $remoteRdmd5" + ) + val isDownloadValid = tdmd5 == remoteTdmd5 && rdmd5 == remoteRdmd5 + Log.i(LOG_TAG_DOWNLOAD, "AppDownloadManager, isDownloadValid? $isDownloadValid") + return isDownloadValid } catch (e: Exception) { - Log.e(LOG_TAG_DOWNLOAD, "AppDownloadManager isDownloadValid exception: ${e.message}", e) + Log.e(LOG_TAG_DOWNLOAD, "AppDownloadManager, isDownloadValid err: ${e.message}", e) } return false } - private fun io(f: suspend () -> Unit) { - CoroutineScope(Dispatchers.IO).launch { f() } - } - private fun ui(f: suspend () -> Unit) { CoroutineScope(Dispatchers.Main).launch { f() } } diff --git a/app/src/full/java/com/celzero/bravedns/ui/fragment/RethinkBlocklistFragment.kt b/app/src/full/java/com/celzero/bravedns/ui/fragment/RethinkBlocklistFragment.kt index e9a831be7..0d97945d7 100644 --- a/app/src/full/java/com/celzero/bravedns/ui/fragment/RethinkBlocklistFragment.kt +++ b/app/src/full/java/com/celzero/bravedns/ui/fragment/RethinkBlocklistFragment.kt @@ -72,12 +72,12 @@ import com.google.android.material.button.MaterialButton import com.google.android.material.button.MaterialButtonToggleGroup import com.google.android.material.chip.Chip import com.google.android.material.dialog.MaterialAlertDialogBuilder +import java.util.regex.Pattern import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import org.koin.android.ext.android.inject import org.koin.androidx.viewmodel.ext.android.viewModel -import java.util.regex.Pattern class RethinkBlocklistFragment : Fragment(R.layout.fragment_rethink_blocklist), SearchView.OnQueryTextListener { @@ -179,7 +179,7 @@ class RethinkBlocklistFragment : selectedFileTags.observe(viewLifecycleOwner) { if (it == null) return@observe - modifiedStamp = RethinkBlocklistManager.getStamp(requireContext(), it, type) + io { modifiedStamp = RethinkBlocklistManager.getStamp(it, type) } } filters.observe(viewLifecycleOwner) { @@ -235,11 +235,6 @@ class RethinkBlocklistFragment : uiCtx { val blocklistsExist = withContext(Dispatchers.IO) { hasBlocklists() } if (blocklistsExist) { - RethinkBlocklistManager.createBraveDns( - requireContext(), - currentBlocklistTimeStamp(), - type - ) setListAdapter() setSimpleAdapter() showConfigureUi() @@ -430,8 +425,7 @@ class RethinkBlocklistFragment : } io { - val blocklistCount = - RethinkBlocklistManager.getTagsFromStamp(requireContext(), stamp, type).size + val blocklistCount = RethinkBlocklistManager.getTagsFromStamp(stamp, type).size if (type.isLocal()) { persistentState.localBlocklistStamp = stamp persistentState.numberOfLocalBlocklists = blocklistCount @@ -496,14 +490,17 @@ class RethinkBlocklistFragment : } private fun setListAdapter() { - processSelectedFileTags(getStamp()) - - if (type.isLocal()) { - setLocalAdapter() - } else { - setRemoteAdapter() + io { + processSelectedFileTags(getStamp()) + uiCtx { + if (type.isLocal()) { + setLocalAdapter() + } else { + setRemoteAdapter() + } + showList(b.lbSimpleToggleBtn.tag.toString()) + } } - showList(b.lbSimpleToggleBtn.tag.toString()) } private fun setSimpleAdapter() { @@ -514,32 +511,30 @@ class RethinkBlocklistFragment : } } - private fun processSelectedFileTags(stamp: String) { - val list = RethinkBlocklistManager.getTagsFromStamp(requireContext(), stamp, type) + private suspend fun processSelectedFileTags(stamp: String) { + val list = RethinkBlocklistManager.getTagsFromStamp(stamp, type) updateSelectedFileTags(list.toMutableSet()) } - private fun updateSelectedFileTags(selectedTags: MutableSet) { - io { - // clear the residues if the selected tags are empty - if (selectedTags.isEmpty()) { - if (type.isLocal()) { - RethinkBlocklistManager.clearTagsSelectionLocal() - } else { - RethinkBlocklistManager.clearTagsSelectionRemote() - } - return@io - } - + private suspend fun updateSelectedFileTags(selectedTags: MutableSet) { + // clear the residues if the selected tags are empty + if (selectedTags.isEmpty()) { if (type.isLocal()) { - RethinkBlocklistManager.updateFiletagsLocal(selectedTags, 1 /* isSelected: true */) - val list = RethinkBlocklistManager.getSelectedFileTagsLocal().toSet() - updateFileTagList(list) + RethinkBlocklistManager.clearTagsSelectionLocal() } else { - RethinkBlocklistManager.updateFiletagsRemote(selectedTags, 1 /* isSelected: true */) - val list = RethinkBlocklistManager.getSelectedFileTagsRemote().toSet() - updateFileTagList(list) + RethinkBlocklistManager.clearTagsSelectionRemote() } + return + } + + if (type.isLocal()) { + RethinkBlocklistManager.updateFiletagsLocal(selectedTags, 1 /* isSelected: true */) + val list = RethinkBlocklistManager.getSelectedFileTagsLocal().toSet() + updateFileTagList(list) + } else { + RethinkBlocklistManager.updateFiletagsRemote(selectedTags, 1 /* isSelected: true */) + val list = RethinkBlocklistManager.getSelectedFileTagsRemote().toSet() + updateFileTagList(list) } } @@ -576,7 +571,7 @@ class RethinkBlocklistFragment : // split: https://max.rethinkdns.com/1:IAAgAA== [https:, , max.rethinkdns.com, 1:IAAgAA==] split.forEach { if (it.contains("$RETHINK_STAMP_VERSION:") && isBase64(it)) { - selectTagsForStamp(it) + io { processSelectedFileTags(it) } showToastUiCentered(requireContext(), "Blocklists restored", Toast.LENGTH_SHORT) return true } @@ -601,10 +596,6 @@ class RethinkBlocklistFragment : return pattern.matcher(result).matches() } - private fun selectTagsForStamp(stamp: String) { - processSelectedFileTags(stamp) - } - fun filterObserver(): MutableLiveData { return filters } diff --git a/app/src/headless/java/com/celzero/bravedns/provider/BlocklistProvider.kt b/app/src/headless/java/com/celzero/bravedns/provider/BlocklistProvider.kt index 3abce78c6..8d44534bb 100644 --- a/app/src/headless/java/com/celzero/bravedns/provider/BlocklistProvider.kt +++ b/app/src/headless/java/com/celzero/bravedns/provider/BlocklistProvider.kt @@ -181,7 +181,7 @@ class BlocklistProvider : ContentProvider() { val context = context ?: return 0 val localFileTags = RethinkLocalFileTag(values) - val count = RethinkBlocklistManager.cpSelectFileTag(context, localFileTags) + val count = RethinkBlocklistManager.cpSelectFileTag(localFileTags) context.contentResolver?.notifyChange(uri, null) return count } diff --git a/app/src/main/java/com/celzero/bravedns/data/AppConfig.kt b/app/src/main/java/com/celzero/bravedns/data/AppConfig.kt index 5a0e996da..dde7b7628 100644 --- a/app/src/main/java/com/celzero/bravedns/data/AppConfig.kt +++ b/app/src/main/java/com/celzero/bravedns/data/AppConfig.kt @@ -42,24 +42,15 @@ import com.celzero.bravedns.database.RethinkDnsEndpointRepository import com.celzero.bravedns.service.PersistentState import com.celzero.bravedns.service.TcpProxyHelper import com.celzero.bravedns.util.Constants -import com.celzero.bravedns.util.Constants.Companion.INIT_TIME_MS -import com.celzero.bravedns.util.Constants.Companion.LOCAL_BLOCKLIST_DOWNLOAD_FOLDER_NAME import com.celzero.bravedns.util.Constants.Companion.MAX_ENDPOINT -import com.celzero.bravedns.util.Constants.Companion.ONDEVICE_BLOCKLIST_FILE_BASIC_CONFIG -import com.celzero.bravedns.util.Constants.Companion.ONDEVICE_BLOCKLIST_FILE_RD -import com.celzero.bravedns.util.Constants.Companion.ONDEVICE_BLOCKLIST_FILE_TAG -import com.celzero.bravedns.util.Constants.Companion.ONDEVICE_BLOCKLIST_FILE_TD import com.celzero.bravedns.util.InternetProtocol import com.celzero.bravedns.util.InternetProtocol.Companion.getInternetProtocol import com.celzero.bravedns.util.KnownPorts.Companion.DNS_PORT import com.celzero.bravedns.util.LoggerConstants.Companion.LOG_TAG_VPN import com.celzero.bravedns.util.OrbotHelper import com.celzero.bravedns.util.PcapMode -import com.celzero.bravedns.util.Utilities import com.celzero.bravedns.util.Utilities.getDnsPort import com.celzero.bravedns.util.Utilities.isAtleastQ -import dnsx.BraveDNS -import dnsx.Dnsx import inet.ipaddr.IPAddressString import intra.Bridge import java.net.InetAddress @@ -83,7 +74,6 @@ internal constructor( private var appTunDnsMode: TunDnsMode = TunDnsMode.NONE private var systemDns: SystemDns = SystemDns("", DNS_PORT) private var braveModeObserver: MutableLiveData = MutableLiveData() - private var braveDns: BraveDNS? = null private var pcapFilePath: String = "" companion object { @@ -95,47 +85,6 @@ internal constructor( init { connectedDns.postValue(persistentState.connectedDnsName) setDnsMode() - createBraveDnsObjectIfNeeded() - } - - private fun createBraveDnsObjectIfNeeded() { - if (!persistentState.blocklistEnabled) return - - try { - val path: String = - Utilities.blocklistDownloadBasePath( - context, - LOCAL_BLOCKLIST_DOWNLOAD_FOLDER_NAME, - persistentState.localBlocklistTimestamp - ) - braveDns = - Dnsx.newBraveDNSLocal( - path + ONDEVICE_BLOCKLIST_FILE_TD, - path + ONDEVICE_BLOCKLIST_FILE_RD, - path + ONDEVICE_BLOCKLIST_FILE_BASIC_CONFIG, - path + ONDEVICE_BLOCKLIST_FILE_TAG - ) - } catch (e: Exception) { - // Set local blocklist enabled to false and reset the timestamp - // if there is a failure creating bravedns - persistentState.blocklistEnabled = false - Log.e(LOG_TAG_VPN, "Local brave dns set exception :${e.message}", e) - // Set local blocklist enabled to false and reset the timestamp to make sure - // user is prompted to download blocklists again on the next try - persistentState.localBlocklistTimestamp = INIT_TIME_MS - } - } - - fun getBraveDnsObj(): BraveDNS? { - if (braveDns == null) { - createBraveDnsObjectIfNeeded() - } - - return braveDns - } - - fun recreateBraveDnsObj() { - createBraveDnsObjectIfNeeded() } data class TunnelOptions( diff --git a/app/src/main/java/com/celzero/bravedns/net/go/GoVpnAdapter.kt b/app/src/main/java/com/celzero/bravedns/net/go/GoVpnAdapter.kt index d070c61db..4663f79ad 100644 --- a/app/src/main/java/com/celzero/bravedns/net/go/GoVpnAdapter.kt +++ b/app/src/main/java/com/celzero/bravedns/net/go/GoVpnAdapter.kt @@ -29,18 +29,21 @@ import com.celzero.bravedns.database.ProxyEndpoint import com.celzero.bravedns.service.PersistentState import com.celzero.bravedns.service.ProxyManager import com.celzero.bravedns.service.ProxyManager.ID_WG_BASE +import com.celzero.bravedns.service.RethinkBlocklistManager import com.celzero.bravedns.service.TcpProxyHelper import com.celzero.bravedns.service.WireGuardManager +import com.celzero.bravedns.util.Constants import com.celzero.bravedns.util.Constants.Companion.ONDEVICE_BLOCKLIST_FILE_TAG import com.celzero.bravedns.util.Constants.Companion.REMOTE_BLOCKLIST_DOWNLOAD_FOLDER_NAME import com.celzero.bravedns.util.LoggerConstants.Companion.LOG_TAG_VPN +import com.celzero.bravedns.util.Utilities import com.celzero.bravedns.util.Utilities.blocklistDir import com.celzero.bravedns.util.Utilities.blocklistFile import com.celzero.bravedns.util.Utilities.isValidPort import com.celzero.bravedns.util.Utilities.showToastUiCentered import com.celzero.bravedns.wireguard.Config -import dnsx.BraveDNS import dnsx.Dnsx +import dnsx.RDNS import dnsx.Transport import inet.ipaddr.HostName import inet.ipaddr.IPAddressString @@ -84,7 +87,7 @@ class GoVpnAdapter : KoinComponent { // part of v055 val dohURL: String = getDefaultDohUrl() - val transport: Transport = makeDefaultTransport(dohURL) // may throw exception + val transport: Transport = makeDefaultTransportLocked(dohURL) // may throw exception Log.i(LOG_TAG_VPN, "Connect with opts $opts, url: $dohURL") // no need to connect tunnel if already connected, just reset the tunnel with new @@ -122,7 +125,7 @@ class GoVpnAdapter : KoinComponent { setPcapModeLocked(appConfig.getPcapFilePath()) addTransportLocked() setDnsAlgLocked() - setBraveDnsBlocklistMode() + setRDNSLocked() } fun setPcapModeLocked(pcapFilePath: String) { @@ -366,24 +369,25 @@ class GoVpnAdapter : KoinComponent { } } - private fun setBraveDnsBlocklistMode() { - if (DEBUG) Log.d(LOG_TAG_VPN, "init rdns modes") + fun setRDNSLocked() { + // Set brave dns to tunnel - Local/Remote + if (DEBUG) Log.d(LOG_TAG_VPN, "set brave dns to tunnel (local/remote)") // enable local blocklist if enabled io { if (persistentState.blocklistEnabled) { - setBraveDNSLocalMode() + setRDNSLocalLocked() } else { // remove local blocklist, if any - tunnel.resolver?.rdnsLocal = null + tunnel.resolver?.setRdnsLocal(null, null, null, null) } // always set the remote blocklist - setBraveDNSRemoteMode() + setRDNSRemoteLocked() } } - private fun setBraveDNSRemoteMode() { + private fun setRDNSRemoteLocked() { if (DEBUG) Log.d(LOG_TAG_VPN, "init remote rdns mode") try { val remoteDir = @@ -396,7 +400,7 @@ class GoVpnAdapter : KoinComponent { val remoteFile = blocklistFile(remoteDir.absolutePath, ONDEVICE_BLOCKLIST_FILE_TAG) ?: return if (remoteFile.exists()) { - tunnel.resolver?.rdnsRemote = Dnsx.newBraveDNSRemote(remoteFile.absolutePath) + tunnel.resolver?.setRdnsRemote(remoteFile.absolutePath) Log.i(LOG_TAG_VPN, "remote-rdns enabled") } else { Log.w(LOG_TAG_VPN, "filetag.json for remote-rdns missing") @@ -524,6 +528,11 @@ class GoVpnAdapter : KoinComponent { } } + fun setCustomProxyLocked(tunProxyMode: AppConfig.TunProxyMode) { + setSocks5TunnelModeIfNeeded(tunProxyMode) + setHttpProxyIfNeeded(tunProxyMode) + } + private fun setSocks5TunnelModeIfNeeded(tunProxyMode: AppConfig.TunProxyMode) { if (!tunProxyMode.isTunProxySocks5() && !tunProxyMode.isTunProxyOrbot()) return @@ -632,8 +641,16 @@ class GoVpnAdapter : KoinComponent { } } + fun getRDNS(type: RethinkBlocklistManager.RethinkBlocklistType): RDNS? { + return if (type.isLocal()) { + tunnel.resolver?.rdnsLocal + } else { + tunnel.resolver?.rdnsRemote + } + } + // v055, unused - private fun setTcpProxyIfNeeded() { + fun setTcpProxyLocked() { if (!appConfig.isTcpProxyEnabled()) { Log.i(LOG_TAG_VPN, "tcp proxy not enabled") return @@ -694,7 +711,7 @@ class GoVpnAdapter : KoinComponent { } @Throws(Exception::class) - private fun makeDefaultTransport(url: String?): Transport { + fun makeDefaultTransportLocked(url: String?): Transport { // when the user has selected none as the dns mode, we use the grounded transport if (url.isNullOrEmpty()) { Log.i(LOG_TAG_VPN, "using grounded transport as default dns is set to none") @@ -738,12 +755,6 @@ class GoVpnAdapter : KoinComponent { } } - fun setBraveDnsBlocklistModeLocked() { - // Set brave dns to tunnel - Local/Remote - if (DEBUG) Log.d(LOG_TAG_VPN, "set brave dns to tunnel (local/remote)") - setBraveDnsBlocklistMode() - } - suspend fun updateLinkLocked(tunFd: ParcelFileDescriptor, opts: TunnelOptions): Boolean { if (!tunnel.isConnected) { Log.e(LOG_TAG_VPN, "updateLink: tunFd is null, returning") @@ -803,31 +814,8 @@ class GoVpnAdapter : KoinComponent { return persistentState.defaultDnsUrl } - private fun setBraveDNSLocalMode() { - try { - val stamp: String = persistentState.localBlocklistStamp - Log.i(LOG_TAG_VPN, "local blocklist stamp: $stamp") - // no need to set braveDNS to tunnel when stamp is empty - if (stamp.isEmpty()) { - return - } - - val braveDNS = makeLocalBraveDns() - if (braveDNS != null) { - tunnel.resolver?.rdnsLocal = braveDNS - tunnel.resolver?.rdnsLocal?.stamp = stamp - Log.i(LOG_TAG_VPN, "local brave dns object is set") - } else { - Log.e(LOG_TAG_VPN, "Issue creating local brave dns object") - } - } catch (ex: Exception) { - persistentState.blocklistEnabled = false - Log.e(LOG_TAG_VPN, "could not set local-brave dns: ${ex.message}", ex) - } - } - // protected by VpnController.mutex - fun setBraveDnsStampLocked() { + fun setRDNSStampLocked() { try { if (tunnel.resolver?.rdnsLocal != null) { Log.i(LOG_TAG_VPN, "set local stamp: ${persistentState.localBlocklistStamp}") @@ -838,11 +826,11 @@ class GoVpnAdapter : KoinComponent { } catch (e: java.lang.Exception) { Log.e(LOG_TAG_VPN, "could not set local stamp: ${e.message}", e) } finally { - resetLocalBlocklistFromTunnel() + resetLocalBlocklistStampFromTunnel() } } - private fun resetLocalBlocklistFromTunnel() { + private fun resetLocalBlocklistStampFromTunnel() { try { if (tunnel.resolver?.rdnsLocal == null) { Log.i(LOG_TAG_VPN, "mode is not local, no need to reset local stamp") @@ -858,8 +846,34 @@ class GoVpnAdapter : KoinComponent { } } - private fun makeLocalBraveDns(): BraveDNS? { - return appConfig.getBraveDnsObj() + private fun setRDNSLocalLocked() { + try { + val stamp: String = persistentState.localBlocklistStamp + Log.i(LOG_TAG_VPN, "local blocklist stamp: $stamp") + + val path: String = + Utilities.blocklistDownloadBasePath( + context, + Constants.LOCAL_BLOCKLIST_DOWNLOAD_FOLDER_NAME, + persistentState.localBlocklistTimestamp + ) + tunnel.resolver?.setRdnsLocal( + path + Constants.ONDEVICE_BLOCKLIST_FILE_TD, + path + Constants.ONDEVICE_BLOCKLIST_FILE_RD, + path + Constants.ONDEVICE_BLOCKLIST_FILE_BASIC_CONFIG, + path + ONDEVICE_BLOCKLIST_FILE_TAG + ) + tunnel.resolver?.rdnsLocal?.stamp = stamp + Log.i(LOG_TAG_VPN, "local brave dns object is set") + } catch (ex: Exception) { + // Set local blocklist enabled to false and reset the timestamp + // if there is a failure creating bravedns + persistentState.blocklistEnabled = false + // Set local blocklist enabled to false and reset the timestamp to make sure + // user is prompted to download blocklists again on the next try + persistentState.localBlocklistTimestamp = Constants.INIT_TIME_MS + Log.e(LOG_TAG_VPN, "could not set local-brave dns: ${ex.message}", ex) + } } companion object { @@ -884,6 +898,16 @@ class GoVpnAdapter : KoinComponent { } } + fun syncP50LatencyLocked() { + try { + val transport = tunnel.resolver?.get(Dnsx.Preferred) + val p50 = transport?.p50() ?: return + persistentState.setMedianLatency(p50) + } catch (e: Exception) { + Log.e(LOG_TAG_VPN, "err getP50: ${e.message}", e) + } + } + private fun io(f: suspend () -> Unit) { externalScope.launch { withContext(Dispatchers.IO) { f() } } } diff --git a/app/src/main/java/com/celzero/bravedns/service/BraveVPNService.kt b/app/src/main/java/com/celzero/bravedns/service/BraveVPNService.kt index ecd950eae..4a4ecc48b 100644 --- a/app/src/main/java/com/celzero/bravedns/service/BraveVPNService.kt +++ b/app/src/main/java/com/celzero/bravedns/service/BraveVPNService.kt @@ -1342,11 +1342,11 @@ class BraveVPNService : notificationManager.notify(SERVICE_ID, updateNotificationBuilder().build()) } PersistentState.LOCAL_BLOCK_LIST -> { - io("localBlocklistEnable") { setBraveDnsBlocklistMode() } + io("localBlocklistEnable") { setRDNS() } } PersistentState.LOCAL_BLOCK_LIST_UPDATE -> { // FIXME: update just that local bravedns obj, not the entire tunnel - io("localBlocklistDownload") { setBraveDnsBlocklistMode() } + io("localBlocklistDownload") { setRDNS() } } PersistentState.BACKGROUND_MODE -> { if (persistentState.getBlockAppWhenBackground()) { @@ -1363,7 +1363,7 @@ class BraveVPNService : if (persistentState.rethinkRemoteUpdate) { io("remoteRethinkUpdates") { addTransport() - setBraveDnsBlocklistMode() + setRDNS() } persistentState.rethinkRemoteUpdate = false } @@ -1371,7 +1371,7 @@ class BraveVPNService : PersistentState.REMOTE_BLOCKLIST_UPDATE -> { io("remoteBlocklistUpdate") { addTransport() - setBraveDnsBlocklistMode() + setRDNS() } } PersistentState.DNS_CHANGE -> { @@ -1465,9 +1465,9 @@ class BraveVPNService : } } - private suspend fun setBraveDnsBlocklistMode() { + private suspend fun setRDNS() { if (DEBUG) Log.d(LOG_TAG_VPN, "set brave dns mode, local/remote") - VpnController.mutex.withLock { vpnAdapter?.setBraveDnsBlocklistModeLocked() } + VpnController.mutex.withLock { vpnAdapter?.setRDNSLocked() } } private suspend fun addTransport() { @@ -2699,4 +2699,12 @@ class BraveVPNService : null } } + + fun syncP50Latency() { + io("syncP50Latency") { + VpnController.mutex.withLock { + vpnAdapter?.syncP50LatencyLocked() + } + } + } } diff --git a/app/src/main/java/com/celzero/bravedns/service/QueryTracker.kt b/app/src/main/java/com/celzero/bravedns/service/QueryTracker.kt index c34e8176c..242369bac 100644 --- a/app/src/main/java/com/celzero/bravedns/service/QueryTracker.kt +++ b/app/src/main/java/com/celzero/bravedns/service/QueryTracker.kt @@ -36,7 +36,7 @@ class QueryTracker(private var persistentState: PersistentState) { } companion object { - private const val HISTORY_SIZE = 1000 + private const val HISTORY_SIZE = 100 } private fun reinitializeQuantileEstimator() { @@ -44,7 +44,7 @@ class QueryTracker(private var persistentState: PersistentState) { numRequests = 1 } - fun recordTransaction(transaction: Transaction) { + suspend fun recordTransaction(transaction: Transaction) { // if server-ip is nil and blocklists are not empty, skip because this tx was resolved // locally if (TextUtils.isEmpty(transaction.serverName) && !TextUtils.isEmpty(transaction.blocklist)) @@ -52,10 +52,15 @@ class QueryTracker(private var persistentState: PersistentState) { ++numRequests if (numRequests % HISTORY_SIZE == 0L) { reinitializeQuantileEstimator() + //refreshP50Latency() } sync(transaction) } + suspend fun refreshP50Latency() { + VpnController.syncP50Latency() + } + fun sync(transaction: Transaction?) { if ( transaction == null || diff --git a/app/src/main/java/com/celzero/bravedns/service/RethinkBlocklistManager.kt b/app/src/main/java/com/celzero/bravedns/service/RethinkBlocklistManager.kt index 1bce7eb84..cd5b0ead3 100644 --- a/app/src/main/java/com/celzero/bravedns/service/RethinkBlocklistManager.kt +++ b/app/src/main/java/com/celzero/bravedns/service/RethinkBlocklistManager.kt @@ -38,17 +38,16 @@ import com.google.common.collect.Multimap import com.google.gson.Gson import com.google.gson.GsonBuilder import com.google.gson.JsonObject -import dnsx.BraveDNS -import dnsx.Dnsx +import dnsx.RDNS +import java.io.IOException +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch import org.koin.core.component.KoinComponent import org.koin.core.component.inject -import java.io.IOException object RethinkBlocklistManager : KoinComponent { - private var braveDnsLocal: BraveDNS? = null - private var braveDnsRemote: BraveDNS? = null - private val remoteFileTagRepository by inject() private val remoteBlocklistPacksMapRepository by inject() private val localFileTagRepository by inject() @@ -347,53 +346,42 @@ object RethinkBlocklistManager : KoinComponent { localFileTagRepository.clearSelectedTags() } - fun cpSelectFileTag(context: Context, localFileTags: RethinkLocalFileTag): Int { - val selectedTags = - getTagsFromStamp( - context, - persistentState.localBlocklistStamp, - RethinkBlocklistType.LOCAL - ) - .toMutableSet() - - // remove the tag from the local blocklist if it exists and current selection is 0 - if (selectedTags.contains(localFileTags.value) && !localFileTags.isSelected) { - selectedTags.remove(localFileTags.value) - } else if (!selectedTags.contains(localFileTags.value) && localFileTags.isSelected) { - // only add the tag if it is not already present - selectedTags.add(localFileTags.value) - } else { - // no-op - } + fun cpSelectFileTag(localFileTags: RethinkLocalFileTag): Int { + io { + val selectedTags = + getTagsFromStamp(persistentState.localBlocklistStamp, RethinkBlocklistType.LOCAL) + .toMutableSet() + + // remove the tag from the local blocklist if it exists and current selection is 0 + if (selectedTags.contains(localFileTags.value) && !localFileTags.isSelected) { + selectedTags.remove(localFileTags.value) + } else if (!selectedTags.contains(localFileTags.value) && localFileTags.isSelected) { + // only add the tag if it is not already present + selectedTags.add(localFileTags.value) + } else { + // no-op + } - val stamp = getStamp(context, selectedTags, RethinkBlocklistType.LOCAL) - persistentState.localBlocklistStamp = stamp + val stamp = getStamp(selectedTags, RethinkBlocklistType.LOCAL) + persistentState.localBlocklistStamp = stamp + } return localFileTagRepository.contentUpdate(localFileTags) } - fun getStamp(context: Context, fileValues: Set, type: RethinkBlocklistType): String { + suspend fun getStamp(fileValues: Set, type: RethinkBlocklistType): String { return try { val flags = convertListToCsv(fileValues) - getBraveDns(context, blocklistTimestamp(type), type)?.flagsToStamp(flags) ?: "" + Log.d("TEST","flags: $flags, type: $type, isRdnsNull(${getRDNS(type)}, getRDNS: ${getRDNS(type)?.flagsToStamp(flags)})}") + getRDNS(type)?.flagsToStamp(flags) ?: "" } catch (e: java.lang.Exception) { Log.e(LoggerConstants.LOG_TAG_VPN, "err stamp2tags: ${e.message}, $e ") "" } } - private fun blocklistTimestamp(type: RethinkBlocklistType): Long { - return if (type.isLocal()) { - persistentState.localBlocklistTimestamp - } else { - persistentState.remoteBlocklistTimestamp - } - } - - fun getTagsFromStamp(context: Context, stamp: String, type: RethinkBlocklistType): Set { + suspend fun getTagsFromStamp(stamp: String, type: RethinkBlocklistType): Set { return try { - convertCsvToList( - getBraveDns(context, blocklistTimestamp(type), type)?.stampToFlags(stamp) - ) + convertCsvToList(getRDNS(type)?.stampToFlags(stamp)) } catch (e: Exception) { Log.e(LoggerConstants.LOG_TAG_VPN, "err tags2stamp: ${e.message}, $e ") setOf() @@ -410,82 +398,11 @@ object RethinkBlocklistManager : KoinComponent { return s.joinToString(",") } - private fun getBraveDnsRemote(context: Context, timestamp: Long): BraveDNS? { - if (braveDnsRemote != null) { - return braveDnsRemote - } - - val dir = - Utilities.blocklistDir(context, REMOTE_BLOCKLIST_DOWNLOAD_FOLDER_NAME, timestamp) - ?: return null - val file = - Utilities.blocklistFile(dir.absolutePath, ONDEVICE_BLOCKLIST_FILE_TAG) ?: return null - - braveDnsRemote = - try { - if (file.exists()) { - Dnsx.newBraveDNSRemote(file.absolutePath) - } else { - Log.e( - LoggerConstants.LOG_TAG_VPN, - "File does not exist in path: ${file.absolutePath}" - ) - null - } - } catch (e: Exception) { - Log.e( - LoggerConstants.LOG_TAG_VPN, - "Exception creating BraveDNS object, ${e.message}, $e " - ) - null - } - return braveDnsRemote - } - - private fun getBraveDnsLocal(context: Context, timestamp: Long): BraveDNS? { - if (braveDnsLocal != null) { - return braveDnsLocal - } - - val dir = - Utilities.blocklistDir(context, LOCAL_BLOCKLIST_DOWNLOAD_FOLDER_NAME, timestamp) - ?: return null - val file = - Utilities.blocklistFile(dir.absolutePath, ONDEVICE_BLOCKLIST_FILE_TAG) ?: return null - braveDnsLocal = - try { - if (file.exists()) { - Dnsx.newBraveDNSRemote(file.absolutePath) - } else { - Log.e( - LoggerConstants.LOG_TAG_VPN, - "File does not exist in path: ${file.absolutePath}" - ) - null - } - } catch (e: Exception) { - Log.e( - LoggerConstants.LOG_TAG_VPN, - "Exception creating BraveDNS object, ${e.message}, $e " - ) - null - } - return braveDnsLocal - } - - private fun getBraveDns( - context: Context, - timestamp: Long, - type: RethinkBlocklistType - ): BraveDNS? { - if (type.isRemote()) { - return getBraveDnsRemote(context, timestamp) - } - - return getBraveDnsLocal(context, timestamp) + private suspend fun getRDNS(type: RethinkBlocklistType): RDNS? { + return VpnController.getRDNS(type) } - fun createBraveDns(context: Context, timestamp: Long, type: RethinkBlocklistType) { - getBraveDns(context, timestamp, type) + private fun io(f: suspend () -> Unit) { + CoroutineScope(Dispatchers.IO).launch { f() } } } diff --git a/app/src/main/java/com/celzero/bravedns/service/VpnController.kt b/app/src/main/java/com/celzero/bravedns/service/VpnController.kt index 55584c111..45d3f89e6 100644 --- a/app/src/main/java/com/celzero/bravedns/service/VpnController.kt +++ b/app/src/main/java/com/celzero/bravedns/service/VpnController.kt @@ -25,6 +25,7 @@ import androidx.lifecycle.MutableLiveData import com.celzero.bravedns.R import com.celzero.bravedns.util.LoggerConstants.Companion.LOG_TAG_VPN import com.celzero.bravedns.util.Utilities +import dnsx.RDNS import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.cancel @@ -206,6 +207,10 @@ object VpnController : KoinComponent { return braveVpnService?.getProxyStatusById(id) } + suspend fun syncP50Latency() { + braveVpnService?.syncP50Latency() + } + fun protocols(): String { val ipv4Size = braveVpnService?.underlyingNetworks?.ipv4Net?.size ?: -1 val ipv6Size = braveVpnService?.underlyingNetworks?.ipv6Net?.size ?: -1 @@ -256,4 +261,8 @@ object VpnController : KoinComponent { fun refreshWireGuardConfig() { braveVpnService?.refreshWireGuardConfig() } + + suspend fun getRDNS(type: RethinkBlocklistManager.RethinkBlocklistType): RDNS? { + return braveVpnService?.getRDNS(type) + } } diff --git a/app/src/main/java/com/celzero/bravedns/util/Utilities.kt b/app/src/main/java/com/celzero/bravedns/util/Utilities.kt index 13d180d5f..e08f3afd8 100644 --- a/app/src/main/java/com/celzero/bravedns/util/Utilities.kt +++ b/app/src/main/java/com/celzero/bravedns/util/Utilities.kt @@ -62,6 +62,7 @@ import com.celzero.bravedns.util.LoggerConstants.Companion.LOG_TAG_FIREWALL import com.celzero.bravedns.util.LoggerConstants.Companion.LOG_TAG_VPN import com.google.common.base.CharMatcher import com.google.common.net.InternetDomainName +import com.google.gson.JsonParser import inet.ipaddr.HostName import inet.ipaddr.IPAddress import inet.ipaddr.IPAddressString @@ -77,6 +78,10 @@ import java.util.Date import java.util.Locale import java.util.concurrent.TimeUnit import kotlinx.coroutines.launch +import okio.HashingSink +import okio.blackholeSink +import okio.buffer +import okio.source object Utilities { @@ -727,4 +732,37 @@ object Utilities { val pre = ("KMGTPE")[exp - 1] + if (si) "" else "i" return String.format("%.1f %sB", bytes / Math.pow(unit.toDouble(), exp.toDouble()), pre) } + + fun calculateMd5(filePath: String): String { + // HashingSink will update the md5sum with every write call and then call down + // to blackholeSink(), ref: https://stackoverflow.com/a/61217039 + return File(filePath).source().buffer().use { source -> + HashingSink.md5(blackholeSink()).use { sink -> + source.readAll(sink) + sink.hash.hex() + } + } + } + + fun getTagValueFromJson(path: String, tag: String): String { + var tagValue = "" + try { + // Read the JSON file + val jsonContent = File(path).readText() + + // Parse JSON using JsonParser + val jsonObject = JsonParser.parseString(jsonContent).asJsonObject + + // Extract the specific tag value + if (jsonObject.has(tag)) { + tagValue = jsonObject.get(tag).asString + Log.i(LOG_TAG_DOWNLOAD, "get tag value: $tagValue, for tag: $tag") + } else { + Log.i(LOG_TAG_DOWNLOAD, "tag not found: $tag") + } + } catch (e: Exception) { + Log.e(LOG_TAG_DOWNLOAD, "err parsing the json file: ${e.message}", e) + } + return tagValue + } }