Commit 6c1970fe authored by Daniel Wolf's avatar Daniel Wolf
Browse files

Merge branch 'master' of https://git.frostnerd.com/PublicAndroidApps/smokescreen into translations

parents 2b954d55 9cd14b49
Pipeline #5833 passed with stages
in 1 minute and 15 seconds
...@@ -120,7 +120,7 @@ dependencies { ...@@ -120,7 +120,7 @@ dependencies {
implementation 'com.frostnerd.utilskt:preferences:1.5.16' // https://git.frostnerd.com/AndroidUtils/preferenceskt implementation 'com.frostnerd.utilskt:preferences:1.5.16' // https://git.frostnerd.com/AndroidUtils/preferenceskt
implementation 'com.frostnerd.utilskt:navigationdraweractivity:1.3.28' // https://git.frostnerd.com/AndroidUtils/navigationdraweractivity implementation 'com.frostnerd.utilskt:navigationdraweractivity:1.3.28' // https://git.frostnerd.com/AndroidUtils/navigationdraweractivity
implementation 'com.frostnerd.utilskt:encrypteddnstunnelproxy:1.5.159' // https://git.frostnerd.com/AndroidUtils/encrypteddnstunnelproxy implementation 'com.frostnerd.utilskt:encrypteddnstunnelproxy:1.5.162' // https://git.frostnerd.com/AndroidUtils/encrypteddnstunnelproxy
implementation 'com.frostnerd.utilskt:general:1.0.18' // https://git.frostnerd.com/AndroidUtils/generalkt implementation 'com.frostnerd.utilskt:general:1.0.18' // https://git.frostnerd.com/AndroidUtils/generalkt
implementation 'com.frostnerd.utilskt:adapters:1.1.5' // https://git.frostnerd.com/AndroidUtils/Adapters implementation 'com.frostnerd.utilskt:adapters:1.1.5' // https://git.frostnerd.com/AndroidUtils/Adapters
......
...@@ -212,8 +212,8 @@ ...@@ -212,8 +212,8 @@
android:exported="false"/> android:exported="false"/>
<service <service
android:name=".service.StartStopTileService" android:name=".service.StartStopTileService"
android:label="@string/quicksettings_start_text" android:label="@string/app_name"
android:icon="@drawable/ic_play" android:icon="@drawable/ic_mainnotification"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"> android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
<intent-filter> <intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE"/> <action android:name="android.service.quicksettings.action.QS_TILE"/>
......
...@@ -56,6 +56,20 @@ class PinActivity: BaseActivity() { ...@@ -56,6 +56,20 @@ class PinActivity: BaseActivity() {
return context.getPreferences().enablePin && (intent == null || !intent.getBooleanExtra("pin_validated", false)) return context.getPreferences().enablePin && (intent == null || !intent.getBooleanExtra("pin_validated", false))
} }
fun openAppIntent(context: Context, extras:Bundle? = null):Intent {
return if(shouldValidatePin(context, null)) {
val intent = Intent(context, PinActivity::class.java)
if(intent.extras != null) intent.putExtra("extras", extras)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.putExtra("pin_type", PinType.APP)
intent
} else {
Intent(context, MainActivity::class.java).apply {
if(extras != null) putExtras(extras)
}
}
}
fun askForPin(context: Context, pinType: PinType, extras:Bundle? = null) { fun askForPin(context: Context, pinType: PinType, extras:Bundle? = null) {
val intent = Intent(context, PinActivity::class.java) val intent = Intent(context, PinActivity::class.java)
if(intent.extras != null) intent.putExtra("extras", extras) if(intent.extras != null) intent.putExtra("extras", extras)
......
...@@ -178,17 +178,19 @@ class SpeedTestActivity : BaseActivity() { ...@@ -178,17 +178,19 @@ class SpeedTestActivity : BaseActivity() {
runOnUiThread { runOnUiThread {
startTest.text = "0/${testsLeft.size}" startTest.text = "0/${testsLeft.size}"
} }
var highestLatency = 500
testsLeft.forEach { pendingTest -> testsLeft.forEach { pendingTest ->
if(testJob?.isCancelled == false) { if(testJob?.isCancelled == false) {
pendingTest.started = true pendingTest.started = true
log("Running SpeedTest for ${pendingTest.server.name}") log("Running SpeedTest for ${pendingTest.server.name}")
val res = DnsSpeedTest(pendingTest.server, 500, 750) { line -> val res = DnsSpeedTest(pendingTest.server, highestLatency, highestLatency+250) { line ->
log(line) log(line)
}.runTest(3) }.runTest(3)
if (res != null) pendingTest.latency = res if (res != null) pendingTest.latency = res
else pendingTest.error = true else pendingTest.error = true
highestLatency = kotlin.math.max(highestLatency, ((pendingTest.latency ?: 0)*1.25).toInt())
testResults!!.sortBy { testResults!!.sortBy {
it.latency ?: Integer.MAX_VALUE it.latency ?: Integer.MAX_VALUE
} }
......
...@@ -69,6 +69,21 @@ interface DnsRuleDao { ...@@ -69,6 +69,21 @@ interface DnsRuleDao {
@Query("SELECT COUNT(*) FROM DnsRule") @Query("SELECT COUNT(*) FROM DnsRule")
fun getCount(): Long fun getCount(): Long
@Query("SELECT COUNT(*) FROM DnsRule WHERE importedFrom is NULL OR IFNULL((SELECT enabled FROM HostSource h WHERE h.id=importedFrom),0) = 1")
fun getActiveCount(): Long
@Query("SELECT host FROM DnsRule WHERE type=255 AND isWildcard=0 AND target='' AND (importedFrom is NULL OR IFNULL((SELECT enabled FROM HostSource h WHERE h.id=importedFrom),0) = 1) ORDER BY RANDOM() LIMIT :count")
fun getRandomNonWildcardWhitelistEntries(count:Int):List<String>
@Query("SELECT COUNT(*) FROM DnsRule WHERE isWildcard=1 AND (importedFrom is NULL OR IFNULL((SELECT enabled FROM HostSource h WHERE h.id=importedFrom),0) = 1)")
fun getActiveWildcardCount(): Long
@Query("SELECT COUNT(*) FROM DnsRule WHERE isWildcard=1 AND target='' AND (importedFrom is NULL OR IFNULL((SELECT enabled FROM HostSource h WHERE h.id=importedFrom),0) = 1)")
fun getActiveWildcardWhitelistCount(): Long
@Query("SELECT COUNT(*) FROM DnsRule WHERE target='' AND (importedFrom is NULL OR IFNULL((SELECT enabled FROM HostSource h WHERE h.id=importedFrom),0) = 1)")
fun getActiveWhitelistCount(): Long
@Query("SELECT COUNT(*) FROM DnsRule WHERE stagingType=0") @Query("SELECT COUNT(*) FROM DnsRule WHERE stagingType=0")
fun getNonStagedCount(): Long fun getNonStagedCount(): Long
...@@ -81,7 +96,7 @@ interface DnsRuleDao { ...@@ -81,7 +96,7 @@ interface DnsRuleDao {
@Query("SELECT CASE WHEN :type=28 THEN IFNULL(ipv6Target, target) ELSE target END FROM DnsRule d1 WHERE d1.host=:host AND d1.target != '' AND (d1.type = :type OR d1.type=255) AND (d1.importedFrom is NULL OR IFNULL((SELECT enabled FROM HostSource h WHERE h.id=d1.importedFrom),0) = 1) AND (d1.importedFrom IS NOT NULL OR :useUserRules=1) AND (SELECT COUNT(*) FROM DnsRule d2 WHERE d2.target='' AND d2.host=:host AND (d2.type = :type OR d2.type=255) AND (d2.importedFrom IS NOT NULL OR :useUserRules=1) AND (importedFrom is NULL OR IFNULL((SELECT enabled FROM HostSource h WHERE h.id=importedFrom),0)))=0 AND isWildcard=0 LIMIT 1") @Query("SELECT CASE WHEN :type=28 THEN IFNULL(ipv6Target, target) ELSE target END FROM DnsRule d1 WHERE d1.host=:host AND d1.target != '' AND (d1.type = :type OR d1.type=255) AND (d1.importedFrom is NULL OR IFNULL((SELECT enabled FROM HostSource h WHERE h.id=d1.importedFrom),0) = 1) AND (d1.importedFrom IS NOT NULL OR :useUserRules=1) AND (SELECT COUNT(*) FROM DnsRule d2 WHERE d2.target='' AND d2.host=:host AND (d2.type = :type OR d2.type=255) AND (d2.importedFrom IS NOT NULL OR :useUserRules=1) AND (importedFrom is NULL OR IFNULL((SELECT enabled FROM HostSource h WHERE h.id=importedFrom),0)))=0 AND isWildcard=0 LIMIT 1")
fun findRuleTarget(host: String, type: Record.TYPE, useUserRules:Boolean): String? fun findRuleTarget(host: String, type: Record.TYPE, useUserRules:Boolean): String?
@Query("SELECT * FROM DnsRule where host=:host AND type=255 AND isWildcard=0 AND target='' AND (importedFrom IS NOT NULL OR :useUserRules=1) AND (importedFrom is NULL OR IFNULL((SELECT enabled FROM HostSource h WHERE h.id=importedFrom),0) = 1)") @Query("SELECT * FROM DnsRule where host=:host AND type=255 AND isWildcard=0 AND target='' AND (importedFrom IS NOT NULL OR :useUserRules=1) AND (importedFrom is NULL OR IFNULL((SELECT enabled FROM HostSource h WHERE h.id=importedFrom),0) = 1) LIMIT 1")
fun findNonWildcardWhitelistEntry(host:String, useUserRules:Boolean):List<DnsRule> fun findNonWildcardWhitelistEntry(host:String, useUserRules:Boolean):List<DnsRule>
@Query("SELECT * FROM DnsRule d1 WHERE ((:includeWhitelistEntries=1 AND d1.target == '') OR (:includeNonWhitelistEntries=1 AND d1.target!='')) AND (d1.type = :type OR d1.type=255) AND (d1.importedFrom is NULL OR IFNULL((SELECT enabled FROM HostSource h WHERE h.id=d1.importedFrom),0) = 1) AND (d1.importedFrom IS NOT NULL OR :useUserRules=1) AND :host LIKE host AND isWildcard=1") @Query("SELECT * FROM DnsRule d1 WHERE ((:includeWhitelistEntries=1 AND d1.target == '') OR (:includeNonWhitelistEntries=1 AND d1.target!='')) AND (d1.type = :type OR d1.type=255) AND (d1.importedFrom is NULL OR IFNULL((SELECT enabled FROM HostSource h WHERE h.id=d1.importedFrom),0) = 1) AND (d1.importedFrom IS NOT NULL OR :useUserRules=1) AND :host LIKE host AND isWildcard=1")
......
...@@ -7,6 +7,7 @@ import androidx.appcompat.app.AlertDialog ...@@ -7,6 +7,7 @@ import androidx.appcompat.app.AlertDialog
import com.frostnerd.smokescreen.R import com.frostnerd.smokescreen.R
import com.frostnerd.smokescreen.database.entities.DnsRule import com.frostnerd.smokescreen.database.entities.DnsRule
import com.frostnerd.smokescreen.getPreferences import com.frostnerd.smokescreen.getPreferences
import com.frostnerd.smokescreen.util.MaxSizeMap
import kotlinx.android.synthetic.main.dialog_create_dnsrule.view.* import kotlinx.android.synthetic.main.dialog_create_dnsrule.view.*
import org.minidns.record.Record import org.minidns.record.Record
import java.net.Inet4Address import java.net.Inet4Address
...@@ -35,7 +36,7 @@ class DnsRuleDialog(context: Context, dnsRule: DnsRule? = null, onRuleCreated: ( ...@@ -35,7 +36,7 @@ class DnsRuleDialog(context: Context, dnsRule: DnsRule? = null, onRuleCreated: (
AlertDialog(context, context.getPreferences().theme.dialogStyle) { AlertDialog(context, context.getPreferences().theme.dialogStyle) {
private var isWhitelist = false private var isWhitelist = false
companion object { companion object {
private val matchers = mutableMapOf<String, Matcher>() private val matchers = MaxSizeMap<String, Matcher>(150, 10)
fun printableHost(host:String): String { fun printableHost(host:String): String {
return host.replace("%%", "**").replace("%", "*") return host.replace("%%", "**").replace("%", "*")
......
...@@ -10,6 +10,7 @@ import android.view.* ...@@ -10,6 +10,7 @@ import android.view.*
import android.widget.Switch import android.widget.Switch
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.work.Constraints import androidx.work.Constraints
...@@ -29,6 +30,7 @@ import com.frostnerd.smokescreen.dialog.DnsRuleDialog ...@@ -29,6 +30,7 @@ import com.frostnerd.smokescreen.dialog.DnsRuleDialog
import com.frostnerd.smokescreen.dialog.ExportDnsRulesDialog import com.frostnerd.smokescreen.dialog.ExportDnsRulesDialog
import com.frostnerd.smokescreen.dialog.HostSourceRefreshDialog import com.frostnerd.smokescreen.dialog.HostSourceRefreshDialog
import com.frostnerd.smokescreen.dialog.NewHostSourceDialog import com.frostnerd.smokescreen.dialog.NewHostSourceDialog
import com.frostnerd.smokescreen.service.DnsVpnService
import com.frostnerd.smokescreen.service.RuleExportService import com.frostnerd.smokescreen.service.RuleExportService
import com.frostnerd.smokescreen.service.RuleImportService import com.frostnerd.smokescreen.service.RuleImportService
import com.frostnerd.smokescreen.util.SpaceItemDecorator import com.frostnerd.smokescreen.util.SpaceItemDecorator
...@@ -213,6 +215,7 @@ class DnsRuleFragment : Fragment() { ...@@ -213,6 +215,7 @@ class DnsRuleFragment : Fragment() {
GlobalScope.launch { GlobalScope.launch {
getDatabase().dnsRuleDao().deleteAllFromSource(it.id) getDatabase().dnsRuleDao().deleteAllFromSource(it.id)
getDatabase().hostSourceDao().delete(it) getDatabase().hostSourceDao().delete(it)
notifyRulesChanged()
} }
dialog.dismiss() dialog.dismiss()
}, getString(R.string.all_no) to { dialog, _ -> }, getString(R.string.all_no) to { dialog, _ ->
...@@ -222,6 +225,7 @@ class DnsRuleFragment : Fragment() { ...@@ -222,6 +225,7 @@ class DnsRuleFragment : Fragment() {
}, changeSourceStatus = { hostSource, enabled -> }, changeSourceStatus = { hostSource, enabled ->
hostSource.enabled = enabled hostSource.enabled = enabled
getDatabase().hostSourceDao().setSourceEnabled(hostSource.id, enabled) getDatabase().hostSourceDao().setSourceEnabled(hostSource.id, enabled)
notifyRulesChanged()
}, editSource = { hostSource -> }, editSource = { hostSource ->
NewHostSourceDialog(context!!, onSourceCreated = { newSource -> NewHostSourceDialog(context!!, onSourceCreated = { newSource ->
val currentSource = getDatabase().hostSourceDao().findById(hostSource.id)!!.apply { val currentSource = getDatabase().hostSourceDao().findById(hostSource.id)!!.apply {
...@@ -260,6 +264,7 @@ class DnsRuleFragment : Fragment() { ...@@ -260,6 +264,7 @@ class DnsRuleFragment : Fragment() {
sourceAdapter.notifyItemRangeRemoved(sourceAdapterList.size + 1, userRuleCount) sourceAdapter.notifyItemRangeRemoved(sourceAdapterList.size + 1, userRuleCount)
} }
userRuleCount = 0 userRuleCount = 0
notifyRulesChanged()
dialog.dismiss() dialog.dismiss()
}, getString(R.string.all_no) to { dialog, _ -> }, getString(R.string.all_no) to { dialog, _ ->
dialog.dismiss() dialog.dismiss()
...@@ -325,6 +330,7 @@ class DnsRuleFragment : Fragment() { ...@@ -325,6 +330,7 @@ class DnsRuleFragment : Fragment() {
list.smoothScrollToPosition(insertPos) list.smoothScrollToPosition(insertPos)
} }
} }
notifyRulesChanged()
} else { } else {
Snackbar.make( Snackbar.make(
activity!!.findViewById(android.R.id.content), activity!!.findViewById(android.R.id.content),
...@@ -350,6 +356,7 @@ class DnsRuleFragment : Fragment() { ...@@ -350,6 +356,7 @@ class DnsRuleFragment : Fragment() {
totalRuleCount = totalRuleCount!! - 1 totalRuleCount = totalRuleCount!! - 1
updateRuleCountTitle() updateRuleCountTitle()
} }
notifyRulesChanged()
}, editRule = { }, editRule = {
DnsRuleDialog(context!!, it) { newRule -> DnsRuleDialog(context!!, it) { newRule ->
val rows = getDatabase().dnsRuleDao().updateIgnore(newRule) val rows = getDatabase().dnsRuleDao().updateIgnore(newRule)
...@@ -447,6 +454,10 @@ class DnsRuleFragment : Fragment() { ...@@ -447,6 +454,10 @@ class DnsRuleFragment : Fragment() {
} }
} }
private fun notifyRulesChanged() {
LocalBroadcastManager.getInstance(context!!).sendBroadcast(Intent(DnsVpnService.BROADCAST_DNSRULES_REFRESHED))
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data) super.onActivityResult(requestCode, resultCode, data)
if(requestCode == fileChosenRequestCode && resultCode == RESULT_OK){ if(requestCode == fileChosenRequestCode && resultCode == RESULT_OK){
......
...@@ -5,6 +5,7 @@ import android.content.Context ...@@ -5,6 +5,7 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import com.frostnerd.smokescreen.activity.BackgroundVpnConfigureActivity import com.frostnerd.smokescreen.activity.BackgroundVpnConfigureActivity
import com.frostnerd.smokescreen.getPreferences import com.frostnerd.smokescreen.getPreferences
import com.frostnerd.smokescreen.util.preferences.VpnServiceState
/* /*
* Copyright (C) 2019 Daniel Wolf (Ch4t4r) * Copyright (C) 2019 Daniel Wolf (Ch4t4r)
...@@ -29,9 +30,18 @@ class AutostartReceiver : BroadcastReceiver() { ...@@ -29,9 +30,18 @@ class AutostartReceiver : BroadcastReceiver() {
if (intent.action != null) { if (intent.action != null) {
var startService = false var startService = false
when { when {
intent.action == Intent.ACTION_MY_PACKAGE_REPLACED -> startService = context.getPreferences().startAppAfterUpdate intent.action == Intent.ACTION_MY_PACKAGE_REPLACED -> {
intent.action == Intent.ACTION_PACKAGE_REPLACED -> startService = intent.data?.schemeSpecificPart == context.packageName && context.getPreferences().startAppAfterUpdate startService = context.getPreferences().startAppAfterUpdate
context.getPreferences().startAppOnBoot -> startService = true context.getPreferences().vpnServiceState = VpnServiceState.STOPPED
}
intent.action == Intent.ACTION_PACKAGE_REPLACED -> {
startService = intent.data?.schemeSpecificPart == context.packageName && context.getPreferences().startAppAfterUpdate
context.getPreferences().vpnServiceState = VpnServiceState.STOPPED
}
context.getPreferences().startAppOnBoot -> {
context.getPreferences().vpnServiceState = VpnServiceState.STOPPED
startService = true
}
} }
if(startService) BackgroundVpnConfigureActivity.prepareVpn(context) if(startService) BackgroundVpnConfigureActivity.prepareVpn(context)
} }
......
...@@ -15,6 +15,7 @@ import android.util.Base64 ...@@ -15,6 +15,7 @@ import android.util.Base64
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import androidx.localbroadcastmanager.content.LocalBroadcastManager import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.frostnerd.dnstunnelproxy.* import com.frostnerd.dnstunnelproxy.*
import com.frostnerd.dnstunnelproxy.QueryListener
import com.frostnerd.encrypteddnstunnelproxy.HttpsDnsServerInformation import com.frostnerd.encrypteddnstunnelproxy.HttpsDnsServerInformation
import com.frostnerd.encrypteddnstunnelproxy.ServerConfiguration import com.frostnerd.encrypteddnstunnelproxy.ServerConfiguration
import com.frostnerd.encrypteddnstunnelproxy.tls.TLSUpstreamAddress import com.frostnerd.encrypteddnstunnelproxy.tls.TLSUpstreamAddress
...@@ -34,10 +35,7 @@ import com.frostnerd.smokescreen.dialog.DnsRuleDialog ...@@ -34,10 +35,7 @@ import com.frostnerd.smokescreen.dialog.DnsRuleDialog
import com.frostnerd.smokescreen.util.DeepActionState import com.frostnerd.smokescreen.util.DeepActionState
import com.frostnerd.smokescreen.util.Notifications import com.frostnerd.smokescreen.util.Notifications
import com.frostnerd.smokescreen.util.preferences.VpnServiceState import com.frostnerd.smokescreen.util.preferences.VpnServiceState
import com.frostnerd.smokescreen.util.proxy.ProxyBypassHandler import com.frostnerd.smokescreen.util.proxy.*
import com.frostnerd.smokescreen.util.proxy.ProxyHttpsHandler
import com.frostnerd.smokescreen.util.proxy.ProxyTlsHandler
import com.frostnerd.smokescreen.util.proxy.SmokeProxy
import com.frostnerd.vpntunnelproxy.FutureAnswer import com.frostnerd.vpntunnelproxy.FutureAnswer
import com.frostnerd.vpntunnelproxy.RetryingVPNTunnelProxy import com.frostnerd.vpntunnelproxy.RetryingVPNTunnelProxy
import com.frostnerd.vpntunnelproxy.TrafficStats import com.frostnerd.vpntunnelproxy.TrafficStats
...@@ -86,7 +84,6 @@ import kotlin.random.Random ...@@ -86,7 +84,6 @@ import kotlin.random.Random
*/ */
class DnsVpnService : VpnService(), Runnable { class DnsVpnService : VpnService(), Runnable {
private var fileDescriptor: ParcelFileDescriptor? = null private var fileDescriptor: ParcelFileDescriptor? = null
private var handle: ProxyHttpsHandler? = null
private var dnsProxy: SmokeProxy? = null private var dnsProxy: SmokeProxy? = null
private var vpnProxy: RetryingVPNTunnelProxy? = null private var vpnProxy: RetryingVPNTunnelProxy? = null
private var destroyed = false private var destroyed = false
...@@ -102,6 +99,7 @@ class DnsVpnService : VpnService(), Runnable { ...@@ -102,6 +99,7 @@ class DnsVpnService : VpnService(), Runnable {
private var connectedToANetwork: Boolean? = null private var connectedToANetwork: Boolean? = null
private var lastScreenOff: Long? = null private var lastScreenOff: Long? = null
private lateinit var screenStateReceiver: BroadcastReceiver private lateinit var screenStateReceiver: BroadcastReceiver
private var dnsRuleRefreshReceiver:BroadcastReceiver? = null
private var simpleNotification = getPreferences().simpleNotification private var simpleNotification = getPreferences().simpleNotification
private var lastVPNStopTime:Long? = null private var lastVPNStopTime:Long? = null
private val coroutineScope:CoroutineContext = SupervisorJob() private val coroutineScope:CoroutineContext = SupervisorJob()
...@@ -115,6 +113,7 @@ class DnsVpnService : VpnService(), Runnable { ...@@ -115,6 +113,7 @@ class DnsVpnService : VpnService(), Runnable {
companion object { companion object {
const val BROADCAST_VPN_ACTIVE = BuildConfig.APPLICATION_ID + ".VPN_ACTIVE" const val BROADCAST_VPN_ACTIVE = BuildConfig.APPLICATION_ID + ".VPN_ACTIVE"
const val BROADCAST_VPN_INACTIVE = BuildConfig.APPLICATION_ID + ".VPN_INACTIVE" const val BROADCAST_VPN_INACTIVE = BuildConfig.APPLICATION_ID + ".VPN_INACTIVE"
const val BROADCAST_DNSRULES_REFRESHED = BuildConfig.APPLICATION_ID + ".DNSRULE_REFRESH"
private const val REQUEST_CODE_IGNORE_SERVICE_KILLED = 10 private const val REQUEST_CODE_IGNORE_SERVICE_KILLED = 10
var currentTrafficStats: TrafficStats? = null var currentTrafficStats: TrafficStats? = null
...@@ -256,6 +255,13 @@ class DnsVpnService : VpnService(), Runnable { ...@@ -256,6 +255,13 @@ class DnsVpnService : VpnService(), Runnable {
} }
} }
} }
dnsRuleRefreshReceiver = registerLocalReceiver(listOf(BROADCAST_DNSRULES_REFRESHED)) {
vpnProxy?.apply {
((packetProxy as DnsPacketProxy).localResolver)?.apply {
(this as DnsRuleResolver).refreshRuleCount()
}
}
}
log("Service created.") log("Service created.")
} }
...@@ -750,7 +756,7 @@ class DnsVpnService : VpnService(), Runnable { ...@@ -750,7 +756,7 @@ class DnsVpnService : VpnService(), Runnable {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
builder.setMetered(false) builder.setMetered(false)
} }
builder.setConfigureIntent(PendingIntent.getActivity(this, 1, Intent(this, MainActivity::class.java), PendingIntent.FLAG_CANCEL_CURRENT)) builder.setConfigureIntent(PendingIntent.getActivity(this, 1, Intent(this, PinActivity::class.java), PendingIntent.FLAG_CANCEL_CURRENT))
val deviceHasIpv6 = hasDeviceIpv6Address() val deviceHasIpv6 = hasDeviceIpv6Address()
val deviceHasIpv4 = hasDeviceIpv4Address() val deviceHasIpv4 = hasDeviceIpv4Address()
...@@ -779,7 +785,7 @@ class DnsVpnService : VpnService(), Runnable { ...@@ -779,7 +785,7 @@ class DnsVpnService : VpnService(), Runnable {
try { try {
builder.addAddress("$prefix.134", mask) builder.addAddress("$prefix.134", mask)
couldSetAddress = true couldSetAddress = true
log("Ipv4-Address set to $prefix.134./$mask") log("Ipv4-Address set to $prefix.134/$mask")
break break
} catch (ignored: IllegalArgumentException) { } catch (ignored: IllegalArgumentException) {
log("Couldn't set Ipv4-Address $prefix.134/$mask") log("Couldn't set Ipv4-Address $prefix.134/$mask")
...@@ -975,37 +981,7 @@ class DnsVpnService : VpnService(), Runnable { ...@@ -975,37 +981,7 @@ class DnsVpnService : VpnService(), Runnable {
log("DnsProxy created, creating VPN proxy") log("DnsProxy created, creating VPN proxy")
vpnProxy = RetryingVPNTunnelProxy(dnsProxy!!, vpnService = this, coroutineScope = CoroutineScope( vpnProxy = RetryingVPNTunnelProxy(dnsProxy!!, vpnService = this, coroutineScope = CoroutineScope(
newFixedThreadPoolContext(2, "proxy-pool") newFixedThreadPoolContext(2, "proxy-pool")
), logger = object : com.frostnerd.vpntunnelproxy.Logger() { ), logger = VpnLogger(applicationContext))
private val tag = (0..5).map { Random.nextInt('a'.toInt(), 'z'.toInt()).toChar() }.joinToString(separator = "")
private val minLogLevel =
if (BuildConfig.DEBUG || getPreferences().advancedLogging) Level.FINE
else if (getPreferences().loggingEnabled) Level.INFO
else Level.OFF
override fun logMessage(message: () -> String, level: Level) {
if (level >= minLogLevel) {
log(message(), "$tag, VPN-LIBRARY, $level")
}
}
override fun failedRequest(question: FutureAnswer, reason: Throwable?) {
if (reason != null && Level.INFO >= minLogLevel) log(
"A request failed: " + Logger.stacktraceToString(reason),
"$tag, VPN-LIBRARY"
)
}
override fun logException(ex: Exception, terminal: Boolean, level: Level) {
if (terminal) log(ex)
else if(Level.INFO >= minLogLevel) log(Logger.stacktraceToString(ex), "$tag, VPN-LIBRARY, $level")
}
override fun logMessage(message: String, level: Level) {
if (level >= minLogLevel) {
log(message, "$tag, VPN-LIBRARY, $level")
}
}
})
vpnProxy?.maxRetries = 15 vpnProxy?.maxRetries = 15
log("VPN proxy creating, trying to run...") log("VPN proxy creating, trying to run...")
...@@ -1022,7 +998,7 @@ class DnsVpnService : VpnService(), Runnable { ...@@ -1022,7 +998,7 @@ class DnsVpnService : VpnService(), Runnable {
private fun createQueryLogger(): QueryListener? { private fun createQueryLogger(): QueryListener? {
return if (getPreferences().shouldLogDnsQueriesToConsole() || getPreferences().queryLoggingEnabled) { return if (getPreferences().shouldLogDnsQueriesToConsole() || getPreferences().queryLoggingEnabled) {
com.frostnerd.smokescreen.util.proxy.QueryListener(this) com.frostnerd.smokescreen.util.proxy.QueryListener(applicationContext)
} else null } else null
} }
...@@ -1088,24 +1064,7 @@ class DnsVpnService : VpnService(), Runnable { ...@@ -1088,24 +1064,7 @@ class DnsVpnService : VpnService(), Runnable {
dnsCache = if (getPreferences().useDnsCache) { dnsCache = if (getPreferences().useDnsCache) {
log("Creating DNS Cache.") log("Creating DNS Cache.")
val cacheControl: CacheControl = if (!getPreferences().useDefaultDnsCacheTime) { val cacheControl: CacheControl = if (!getPreferences().useDefaultDnsCacheTime) {
val cacheTime = getPreferences().customDnsCacheTime.toLong() NxDomainCacheControl(applicationContext)
val nxDomainCacheTime = getPreferences().nxDomainCacheTime.toLong()
object : CacheControl {
override suspend fun getTtl(
answerMessage: DnsMessage,
dnsName: DnsName,
type: Record.TYPE,
record: Record<*>
): Long {
return if (answerMessage.responseCode == DnsMessage.RESPONSE_CODE.NX_DOMAIN) nxDomainCacheTime else cacheTime
}
override suspend fun getTtl(question: Question, record: Record<*>): Long =
cacheTime
override fun shouldCache(question: Question): Boolean = true
}
} else DefaultCacheControl(getPreferences().minimumCacheTime.toLong()) } else DefaultCacheControl(getPreferences().minimumCacheTime.toLong())
val onClearCache: ((currentCache: Map<String, Map<Record.TYPE, Map<Record<*>, Long>>>) -> Unit)? = val onClearCache: ((currentCache: Map<String, Map<Record.TYPE, Map<Record<*>, Long>>>) -> Unit)? =
if (getPreferences().keepDnsCacheAcrossLaunches) { if (getPreferences().keepDnsCacheAcrossLaunches) {
...@@ -1186,108 +1145,10 @@ class DnsVpnService : VpnService(), Runnable { ...@@ -1186,108 +1145,10 @@ class DnsVpnService : VpnService(), Runnable {
} }
private fun createLocalResolver(): LocalResolver? { private fun createLocalResolver(): LocalResolver? {
if (getPreferences().dnsRulesEnabled) { return if (getPreferences().dnsRulesEnabled) {
return object : LocalResolver(false) { DnsRuleResolver(applicationContext)
private val dao = getDatabase().dnsRuleDao()
private val resolveResults = mutableMapOf<Question, String>()
private val wwwRegex = Regex("^www\\.")
private val useUserRules = getPreferences().customHostsEnabled
override suspend fun canResolve(question: Question): Boolean {
return if (question.type != Record.TYPE.A && question.type != Record.TYPE.AAAA) {
false
} else {
val uniformQuestion = question.name.toString().replace(wwwRegex, "")
val isWhitelisted = dao.findPossibleWildcardRuleTarget(
uniformQuestion,
question.type,
useUserRules,
true,
false
).any {
DnsRuleDialog.databaseHostToMatcher(it.host).reset(uniformQuestion)
.matches()
} || dao.findNonWildcardWhitelistEntry(
uniformQuestion,
useUserRules
).isNotEmpty()
if (isWhitelisted) false
else {
val resolveResult =
dao.findRuleTarget(uniformQuestion, question.type, useUserRules)
?.let {
when (it) {
"0" -> "0.0.0.0"
"1" -> {
if (question.type == Record.TYPE.AAAA) "::1"
else "127.0.0.1"
}
else -> it
}
}
if (resolveResult != null) {
resolveResults[question] = resolveResult
true
} else {
val wildcardResolveResults = dao.findPossibleWildcardRuleTarget(
uniformQuestion,
question.type,
useUserRules,
false,
true
).filter {
DnsRuleDialog.databaseHostToMatcher(it.host)
.reset(uniformQuestion).matches()
}