summaryrefslogtreecommitdiff
path: root/ipscrambling/src
diff options
context:
space:
mode:
Diffstat (limited to 'ipscrambling/src')
-rw-r--r--ipscrambling/src/main/java/foundation/e/advancedprivacy/ipscrambler/KoinModule.kt2
-rw-r--r--ipscrambling/src/main/java/foundation/e/advancedprivacy/ipscrambler/OrbotServiceSupervisor.kt (renamed from ipscrambling/src/main/java/foundation/e/advancedprivacy/ipscrambler/IpScramblerModule.kt)132
2 files changed, 67 insertions, 67 deletions
diff --git a/ipscrambling/src/main/java/foundation/e/advancedprivacy/ipscrambler/KoinModule.kt b/ipscrambling/src/main/java/foundation/e/advancedprivacy/ipscrambler/KoinModule.kt
index bfb9b32..79aeb05 100644
--- a/ipscrambling/src/main/java/foundation/e/advancedprivacy/ipscrambler/KoinModule.kt
+++ b/ipscrambling/src/main/java/foundation/e/advancedprivacy/ipscrambler/KoinModule.kt
@@ -21,5 +21,5 @@ import org.koin.core.module.dsl.singleOf
import org.koin.dsl.module
val ipScramblerModule = module {
- singleOf(::IpScramblerModule)
+ singleOf(::OrbotServiceSupervisor)
}
diff --git a/ipscrambling/src/main/java/foundation/e/advancedprivacy/ipscrambler/IpScramblerModule.kt b/ipscrambling/src/main/java/foundation/e/advancedprivacy/ipscrambler/OrbotServiceSupervisor.kt
index d1f01a0..8813948 100644
--- a/ipscrambling/src/main/java/foundation/e/advancedprivacy/ipscrambler/IpScramblerModule.kt
+++ b/ipscrambling/src/main/java/foundation/e/advancedprivacy/ipscrambler/OrbotServiceSupervisor.kt
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2023 MURENA SAS
* Copyright (C) 2021 E FOUNDATION
*
* This program is free software: you can redistribute it and/or modify
@@ -27,28 +28,37 @@ import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.os.Message
-import android.util.Log
import androidx.localbroadcastmanager.content.LocalBroadcastManager
+import foundation.e.advancedprivacy.domain.entities.FeatureServiceState
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.update
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+import org.pcap4j.packet.DnsPacket
import org.torproject.android.service.OrbotConstants
import org.torproject.android.service.OrbotConstants.ACTION_STOP_FOREGROUND_TASK
import org.torproject.android.service.OrbotService
import org.torproject.android.service.util.Prefs
+import timber.log.Timber
import java.security.InvalidParameterException
+import java.util.function.Function
@SuppressLint("CommitPrefEdits")
-class IpScramblerModule(private val context: Context) {
- interface Listener {
- fun onStatusChanged(newStatus: Status)
- fun log(message: String)
- fun onTrafficUpdate(upload: Long, download: Long, read: Long, write: Long)
- }
+class OrbotServiceSupervisor(
+ private val context: Context,
+ private val coroutineScope: CoroutineScope,
+) {
+ private val _state = MutableStateFlow(FeatureServiceState.OFF)
+ val state: StateFlow<FeatureServiceState> = _state
enum class Status {
OFF, ON, STARTING, STOPPING, START_DISABLED
}
companion object {
- const val TAG = "IpScramblerModule"
-
private val EXIT_COUNTRY_CODES = setOf("DE", "AT", "SE", "CH", "IS", "CA", "US", "ES", "FR", "BG", "PL", "AU", "BR", "CZ", "DK", "FI", "GB", "HU", "NL", "JP", "RO", "RU", "SG", "SK")
// Key where exit country is stored by orbot service.
@@ -58,7 +68,6 @@ class IpScramblerModule(private val context: Context) {
}
private var currentStatus: Status? = null
- private val listeners = mutableSetOf<Listener>()
private val localBroadcastReceiver: BroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
@@ -70,7 +79,7 @@ class IpScramblerModule(private val context: Context) {
currentStatus = newStatus
}
} catch (e: Exception) {
- Log.e(TAG, "Can't parse Orbot service status.")
+ Timber.e("Can't parse Orbot service status.")
}
return
}
@@ -87,18 +96,6 @@ class IpScramblerModule(private val context: Context) {
val action = msg.obj as? String ?: return
val data = msg.data
when (action) {
- OrbotConstants.LOCAL_ACTION_LOG ->
- data.getString(OrbotConstants.LOCAL_EXTRA_LOG)?.let { newLog(it) }
-
- OrbotConstants.LOCAL_ACTION_BANDWIDTH -> {
- trafficUpdate(
- data.getLong("up", 0),
- data.getLong("down", 0),
- data.getLong("written", 0),
- data.getLong("read", 0)
- )
- }
-
OrbotConstants.LOCAL_ACTION_PORTS -> {
httpProxyPort = data.getInt(OrbotService.EXTRA_HTTP_PROXY_PORT, -1)
socksProxyPort = data.getInt(OrbotService.EXTRA_SOCKS_PROXY_PORT, -1)
@@ -110,9 +107,11 @@ class IpScramblerModule(private val context: Context) {
val newStatus = Status.valueOf(it)
updateStatus(newStatus, force = true)
} catch (e: Exception) {
- Log.e(TAG, "Can't parse Orbot service status.")
+ Timber.e("Can't parse Orbot service status.")
}
}
+ OrbotConstants.LOCAL_ACTION_LOG,
+ OrbotConstants.LOCAL_ACTION_BANDWIDTH -> {} // Unused in Advanced Privacy
}
super.handleMessage(msg)
}
@@ -150,9 +149,24 @@ class IpScramblerModule(private val context: Context) {
private fun updateStatus(status: Status, force: Boolean = false) {
if (force || status != currentStatus) {
- currentStatus = status
- listeners.forEach {
- it.onStatusChanged(status)
+ val newState = when (status) {
+ Status.OFF -> FeatureServiceState.OFF
+ Status.ON -> FeatureServiceState.ON
+ Status.STARTING -> FeatureServiceState.STARTING
+ Status.STOPPING,
+ Status.START_DISABLED -> FeatureServiceState.STOPPING
+ }
+
+ coroutineScope.launch(Dispatchers.IO) {
+ _state.update { currentState ->
+ if (newState == FeatureServiceState.OFF &&
+ currentState == FeatureServiceState.STOPPING
+ ) {
+ // Wait for orbot to relax before allowing user to reactivate it.
+ delay(1000)
+ }
+ newState
+ }
}
}
}
@@ -165,14 +179,6 @@ class IpScramblerModule(private val context: Context) {
return currentStatus != Status.OFF
}
- private fun newLog(message: String) {
- listeners.forEach { it.log(message) }
- }
-
- private fun trafficUpdate(upload: Long, download: Long, read: Long, write: Long) {
- listeners.forEach { it.onTrafficUpdate(upload, download, read, write) }
- }
-
private fun sendIntentToService(action: String, extra: Bundle? = null) {
val intent = Intent(context, OrbotService::class.java)
intent.action = action
@@ -203,27 +209,29 @@ class IpScramblerModule(private val context: Context) {
}
@SuppressLint("ApplySharedPref")
- private fun setExitCountryCode(countryCode: String) {
- val countryParam = when {
- countryCode.isEmpty() -> ""
- countryCode in EXIT_COUNTRY_CODES -> "{$countryCode}"
- else -> throw InvalidParameterException(
- "Only these countries are available: ${EXIT_COUNTRY_CODES.joinToString { ", " } }"
- )
- }
+ suspend fun setExitCountryCode(countryCode: String) {
+ withContext(Dispatchers.IO) {
+ val countryParam = when {
+ countryCode.isEmpty() -> ""
+ countryCode in EXIT_COUNTRY_CODES -> "{$countryCode}"
+ else -> throw InvalidParameterException(
+ "Only these countries are available: ${EXIT_COUNTRY_CODES.joinToString { ", " }}"
+ )
+ }
- if (isServiceRunning()) {
- val extra = Bundle()
- extra.putString("exit", countryParam)
- sendIntentToService(OrbotConstants.CMD_SET_EXIT, extra)
- } else {
- Prefs.getSharedPrefs(context)
- .edit().putString(PREFS_KEY_EXIT_NODES, countryParam)
- .commit()
+ if (isServiceRunning()) {
+ val extra = Bundle()
+ extra.putString("exit", countryParam)
+ sendIntentToService(OrbotConstants.CMD_SET_EXIT, extra)
+ } else {
+ Prefs.getSharedPrefs(context)
+ .edit().putString(PREFS_KEY_EXIT_NODES, countryParam)
+ .commit()
+ }
}
}
- private fun getExitCountryCode(): String {
+ fun getExitCountryCode(): String {
val raw = Prefs.getExitNodes()
return if (raw.isEmpty()) raw else raw.slice(1..2)
}
@@ -232,6 +240,10 @@ class IpScramblerModule(private val context: Context) {
return VpnService.prepare(context)
}
+ fun setDNSFilter(shouldBlock: Function<DnsPacket?, DnsPacket?>?) {
+ OrbotService.shouldBlock = shouldBlock
+ }
+
fun start(enableNotification: Boolean) {
Prefs.enableNotification(enableNotification)
Prefs.putUseVpn(true)
@@ -242,6 +254,8 @@ class IpScramblerModule(private val context: Context) {
}
fun stop() {
+ if (!isServiceRunning()) return
+
updateStatus(Status.STOPPING)
Prefs.putUseVpn(false)
@@ -280,10 +294,6 @@ class IpScramblerModule(private val context: Context) {
get() = getTorifiedApps()
set(value) = saveTorifiedApps(value)
- var exitCountry: String
- get() = getExitCountryCode()
- set(value) = setExitCountryCode(value)
-
fun getAvailablesLocations(): Set<String> = EXIT_COUNTRY_CODES
var httpProxyPort: Int = -1
@@ -292,16 +302,6 @@ class IpScramblerModule(private val context: Context) {
var socksProxyPort: Int = -1
private set
- fun addListener(listener: Listener) {
- listeners.add(listener)
- }
- fun removeListener(listener: Listener) {
- listeners.remove(listener)
- }
- fun clearListeners() {
- listeners.clear()
- }
-
fun onCleared() {
LocalBroadcastManager.getInstance(context).unregisterReceiver(localBroadcastReceiver)
}