diff --git a/app/schemas/com.zaneschepke.wireguardautotunnel.data.AppDatabase/21.json b/app/schemas/com.zaneschepke.wireguardautotunnel.data.AppDatabase/21.json new file mode 100644 index 00000000..75ad4171 --- /dev/null +++ b/app/schemas/com.zaneschepke.wireguardautotunnel.data.AppDatabase/21.json @@ -0,0 +1,359 @@ +{ + "formatVersion": 1, + "database": { + "version": 21, + "identityHash": "51f828868c0ea2f0f5c987410ff5c5a1", + "entities": [ + { + "tableName": "Settings", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_tunnel_enabled` INTEGER NOT NULL, `is_tunnel_on_mobile_data_enabled` INTEGER NOT NULL, `trusted_network_ssids` TEXT NOT NULL, `is_always_on_vpn_enabled` INTEGER NOT NULL, `is_tunnel_on_ethernet_enabled` INTEGER NOT NULL, `is_shortcuts_enabled` INTEGER NOT NULL DEFAULT false, `is_tunnel_on_wifi_enabled` INTEGER NOT NULL DEFAULT false, `is_restore_on_boot_enabled` INTEGER NOT NULL DEFAULT false, `is_multi_tunnel_enabled` INTEGER NOT NULL DEFAULT false, `is_ping_enabled` INTEGER NOT NULL DEFAULT false, `is_wildcards_enabled` INTEGER NOT NULL DEFAULT false, `is_stop_on_no_internet_enabled` INTEGER NOT NULL DEFAULT false, `is_lan_on_kill_switch_enabled` INTEGER NOT NULL DEFAULT false, `debounce_delay_seconds` INTEGER NOT NULL DEFAULT 3, `is_disable_kill_switch_on_trusted_enabled` INTEGER NOT NULL DEFAULT false, `is_tunnel_on_unsecure_enabled` INTEGER NOT NULL DEFAULT false, `wifi_detection_method` INTEGER NOT NULL DEFAULT 0, `is_ping_monitoring_enabled` INTEGER NOT NULL DEFAULT true, `tunnel_ping_interval_sec` INTEGER NOT NULL DEFAULT 30, `tunnel_ping_attempts` INTEGER NOT NULL DEFAULT 3, `tunnel_ping_timeout_sec` INTEGER, `app_mode` INTEGER NOT NULL DEFAULT 0, `dns_protocol` INTEGER NOT NULL DEFAULT 0, `dns_endpoint` TEXT)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isAutoTunnelEnabled", + "columnName": "is_tunnel_enabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isTunnelOnMobileDataEnabled", + "columnName": "is_tunnel_on_mobile_data_enabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "trustedNetworkSSIDs", + "columnName": "trusted_network_ssids", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "isAlwaysOnVpnEnabled", + "columnName": "is_always_on_vpn_enabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isTunnelOnEthernetEnabled", + "columnName": "is_tunnel_on_ethernet_enabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isShortcutsEnabled", + "columnName": "is_shortcuts_enabled", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "false" + }, + { + "fieldPath": "isTunnelOnWifiEnabled", + "columnName": "is_tunnel_on_wifi_enabled", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "false" + }, + { + "fieldPath": "isRestoreOnBootEnabled", + "columnName": "is_restore_on_boot_enabled", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "false" + }, + { + "fieldPath": "isMultiTunnelEnabled", + "columnName": "is_multi_tunnel_enabled", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "false" + }, + { + "fieldPath": "isPingEnabled", + "columnName": "is_ping_enabled", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "false" + }, + { + "fieldPath": "isWildcardsEnabled", + "columnName": "is_wildcards_enabled", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "false" + }, + { + "fieldPath": "isStopOnNoInternetEnabled", + "columnName": "is_stop_on_no_internet_enabled", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "false" + }, + { + "fieldPath": "isLanOnKillSwitchEnabled", + "columnName": "is_lan_on_kill_switch_enabled", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "false" + }, + { + "fieldPath": "debounceDelaySeconds", + "columnName": "debounce_delay_seconds", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "3" + }, + { + "fieldPath": "isDisableKillSwitchOnTrustedEnabled", + "columnName": "is_disable_kill_switch_on_trusted_enabled", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "false" + }, + { + "fieldPath": "isTunnelOnUnsecureEnabled", + "columnName": "is_tunnel_on_unsecure_enabled", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "false" + }, + { + "fieldPath": "wifiDetectionMethod", + "columnName": "wifi_detection_method", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "isPingMonitoringEnabled", + "columnName": "is_ping_monitoring_enabled", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "true" + }, + { + "fieldPath": "tunnelPingIntervalSeconds", + "columnName": "tunnel_ping_interval_sec", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "30" + }, + { + "fieldPath": "tunnelPingAttempts", + "columnName": "tunnel_ping_attempts", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "3" + }, + { + "fieldPath": "tunnelPingTimeoutSeconds", + "columnName": "tunnel_ping_timeout_sec", + "affinity": "INTEGER" + }, + { + "fieldPath": "appMode", + "columnName": "app_mode", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "dnsProtocol", + "columnName": "dns_protocol", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "dnsEndpoint", + "columnName": "dns_endpoint", + "affinity": "TEXT" + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + } + }, + { + "tableName": "TunnelConfig", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `wg_quick` TEXT NOT NULL, `tunnel_networks` TEXT NOT NULL DEFAULT '', `is_mobile_data_tunnel` INTEGER NOT NULL DEFAULT false, `is_primary_tunnel` INTEGER NOT NULL DEFAULT false, `am_quick` TEXT NOT NULL DEFAULT '', `is_Active` INTEGER NOT NULL DEFAULT false, `restart_on_ping_failure` INTEGER NOT NULL DEFAULT false, `ping_target` TEXT DEFAULT null, `is_ethernet_tunnel` INTEGER NOT NULL DEFAULT false, `is_ipv4_preferred` INTEGER NOT NULL DEFAULT true, `position` INTEGER NOT NULL DEFAULT 0, `auto_tunnel_apps` TEXT NOT NULL DEFAULT '[]')", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "wgQuick", + "columnName": "wg_quick", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "tunnelNetworks", + "columnName": "tunnel_networks", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "isMobileDataTunnel", + "columnName": "is_mobile_data_tunnel", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "false" + }, + { + "fieldPath": "isPrimaryTunnel", + "columnName": "is_primary_tunnel", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "false" + }, + { + "fieldPath": "amQuick", + "columnName": "am_quick", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "isActive", + "columnName": "is_Active", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "false" + }, + { + "fieldPath": "restartOnPingFailure", + "columnName": "restart_on_ping_failure", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "false" + }, + { + "fieldPath": "pingTarget", + "columnName": "ping_target", + "affinity": "TEXT", + "defaultValue": "null" + }, + { + "fieldPath": "isEthernetTunnel", + "columnName": "is_ethernet_tunnel", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "false" + }, + { + "fieldPath": "isIpv4Preferred", + "columnName": "is_ipv4_preferred", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "true" + }, + { + "fieldPath": "position", + "columnName": "position", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "autoTunnelApps", + "columnName": "auto_tunnel_apps", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "'[]'" + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_TunnelConfig_name", + "unique": true, + "columnNames": [ + "name" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_TunnelConfig_name` ON `${TABLE_NAME}` (`name`)" + } + ] + }, + { + "tableName": "proxy_settings", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `socks5_proxy_enabled` INTEGER NOT NULL DEFAULT false, `socks5_proxy_bind_address` TEXT, `http_proxy_enable` INTEGER NOT NULL DEFAULT false, `http_proxy_bind_address` TEXT, `proxy_username` TEXT, `proxy_password` TEXT)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "socks5ProxyEnabled", + "columnName": "socks5_proxy_enabled", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "false" + }, + { + "fieldPath": "socks5ProxyBindAddress", + "columnName": "socks5_proxy_bind_address", + "affinity": "TEXT" + }, + { + "fieldPath": "httpProxyEnabled", + "columnName": "http_proxy_enable", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "false" + }, + { + "fieldPath": "httpProxyBindAddress", + "columnName": "http_proxy_bind_address", + "affinity": "TEXT" + }, + { + "fieldPath": "proxyUsername", + "columnName": "proxy_username", + "affinity": "TEXT" + }, + { + "fieldPath": "proxyPassword", + "columnName": "proxy_password", + "affinity": "TEXT" + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + } + } + ], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '51f828868c0ea2f0f5c987410ff5c5a1')" + ] + } +} \ No newline at end of file diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/notification/NotificationMonitor.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/notification/NotificationMonitor.kt index c1b25800..519a021c 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/notification/NotificationMonitor.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/notification/NotificationMonitor.kt @@ -3,7 +3,7 @@ package com.zaneschepke.wireguardautotunnel.core.notification import com.zaneschepke.wireguardautotunnel.R import com.zaneschepke.wireguardautotunnel.WireGuardAutoTunnel import com.zaneschepke.wireguardautotunnel.core.tunnel.TunnelManager -import com.zaneschepke.wireguardautotunnel.domain.events.BackendError +import com.zaneschepke.wireguardautotunnel.domain.events.BackendCoreException import com.zaneschepke.wireguardautotunnel.util.StringValue import jakarta.inject.Inject import kotlinx.coroutines.coroutineScope @@ -30,7 +30,7 @@ constructor( title = StringValue.DynamicString(tunnelConf.name), description = when (error) { - is BackendError.BounceFailed -> error.toStringValue() + is BackendCoreException.BounceFailed -> error.toStringValue() else -> StringValue.StringResource( R.string.tunnel_error_template, diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/BaseTunnel.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/BaseTunnel.kt index a0cb8184..de7eecfe 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/BaseTunnel.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/BaseTunnel.kt @@ -3,7 +3,7 @@ package com.zaneschepke.wireguardautotunnel.core.tunnel import com.wireguard.android.backend.Tunnel import com.zaneschepke.wireguardautotunnel.core.service.ServiceManager import com.zaneschepke.wireguardautotunnel.domain.enums.TunnelStatus -import com.zaneschepke.wireguardautotunnel.domain.events.BackendError +import com.zaneschepke.wireguardautotunnel.domain.events.BackendCoreException import com.zaneschepke.wireguardautotunnel.domain.events.BackendMessage import com.zaneschepke.wireguardautotunnel.domain.model.TunnelConf import com.zaneschepke.wireguardautotunnel.domain.repository.AppDataRepository @@ -30,7 +30,7 @@ abstract class BaseTunnel( private val serviceManager: ServiceManager, ) : TunnelProvider { - private val _errorEvents = MutableSharedFlow>() + private val _errorEvents = MutableSharedFlow>() override val errorEvents = _errorEvents.asSharedFlow() private val _messageEvents = MutableSharedFlow>() @@ -154,7 +154,7 @@ abstract class BaseTunnel( var currentConf = tunnelConf var restoreAttempted = false - var originalError: BackendError? = null + var originalError: BackendCoreException? = null while (true) { try { @@ -169,7 +169,7 @@ abstract class BaseTunnel( _messageEvents.emit(tunnelConf to BackendMessage.BounceSuccess) } return // Success, return - } catch (e: BackendError) { + } catch (e: BackendCoreException) { originalError = originalError ?: e val bounceReason = bouncingTunnelIds[currentConf.id] if (!restoreAttempted && bounceReason is TunnelStatus.StopReason.Ping) { @@ -209,7 +209,7 @@ abstract class BaseTunnel( } Timber.e(e, "Failed to start backend for ${currentConf.name}") val emitError = - if (restoreAttempted) BackendError.BounceFailed(originalError) else e + if (restoreAttempted) BackendCoreException.BounceFailed(originalError) else e _errorEvents.emit(currentConf to emitError) updateTunnelStatus(currentConf, TunnelStatus.Down) return @@ -238,7 +238,7 @@ abstract class BaseTunnel( stopBackend(tunnel) saveTunnelActiveState(tunnelConf, false) removeActiveTunnel(tunnel) - } catch (e: BackendError) { + } catch (e: BackendCoreException) { Timber.e(e, "Failed to stop tunnel ${tunnelConf.id}") _errorEvents.emit(tunnelConf to e) updateTunnelStatus(tunnelConf, TunnelStatus.Down) diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/KernelTunnel.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/KernelTunnel.kt index de218309..75905752 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/KernelTunnel.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/KernelTunnel.kt @@ -8,12 +8,12 @@ import com.zaneschepke.wireguardautotunnel.di.ApplicationScope import com.zaneschepke.wireguardautotunnel.di.Kernel import com.zaneschepke.wireguardautotunnel.domain.enums.BackendMode import com.zaneschepke.wireguardautotunnel.domain.enums.TunnelStatus -import com.zaneschepke.wireguardautotunnel.domain.events.BackendError +import com.zaneschepke.wireguardautotunnel.domain.events.BackendCoreException import com.zaneschepke.wireguardautotunnel.domain.model.TunnelConf import com.zaneschepke.wireguardautotunnel.domain.repository.AppDataRepository import com.zaneschepke.wireguardautotunnel.domain.state.TunnelStatistics import com.zaneschepke.wireguardautotunnel.domain.state.WireGuardStatistics -import com.zaneschepke.wireguardautotunnel.util.extensions.toBackendError +import com.zaneschepke.wireguardautotunnel.util.extensions.toBackendCoreException import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import timber.log.Timber @@ -38,16 +38,16 @@ constructor( override suspend fun startBackend(tunnel: TunnelConf) { // name too long for kernel mode - if (!tunnel.isNameKernelCompatible) throw BackendError.TunnelNameTooLong + if (!tunnel.isNameKernelCompatible) throw BackendCoreException.TunnelNameTooLong try { updateTunnelStatus(tunnel, TunnelStatus.Starting) backend.setState(tunnel, Tunnel.State.UP, tunnel.toWgConfig()) } catch (e: BackendException) { Timber.e(e, "Failed to start up backend for tunnel ${tunnel.name}") - throw e.toBackendError() + throw e.toBackendCoreException() } catch (e: IllegalArgumentException) { Timber.e(e, "Failed to start up backend for tunnel ${tunnel.name}") - throw BackendError.Config + throw BackendCoreException.Config } } @@ -56,7 +56,7 @@ constructor( try { backend.setState(tunnel, Tunnel.State.DOWN, tunnel.toWgConfig()) } catch (e: BackendException) { - throw e.toBackendError() + throw e.toBackendCoreException() } } diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/TunnelManager.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/TunnelManager.kt index d1afabd0..5613ceae 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/TunnelManager.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/TunnelManager.kt @@ -5,7 +5,7 @@ import com.zaneschepke.wireguardautotunnel.data.model.AppMode import com.zaneschepke.wireguardautotunnel.di.* import com.zaneschepke.wireguardautotunnel.domain.enums.BackendMode import com.zaneschepke.wireguardautotunnel.domain.enums.TunnelStatus -import com.zaneschepke.wireguardautotunnel.domain.events.BackendError +import com.zaneschepke.wireguardautotunnel.domain.events.BackendCoreException import com.zaneschepke.wireguardautotunnel.domain.events.BackendMessage import com.zaneschepke.wireguardautotunnel.domain.model.AppSettings import com.zaneschepke.wireguardautotunnel.domain.model.TunnelConf @@ -79,7 +79,15 @@ constructor( val allowedIps = if (settings.isLanOnKillSwitchEnabled) TunnelConf.IPV4_PUBLIC_NETWORKS else emptySet() - proxyUserspaceTunnel.setBackendMode(BackendMode.KillSwitch(allowedIps)) + try { + // TODO handle situation where they don't have vpn permission, request it + if (hasVpnPermission()) { + proxyUserspaceTunnel.setBackendMode(BackendMode.KillSwitch(allowedIps)) + } + } catch (e: BackendCoreException) { + // TODO expose this error to user + Timber.e(e) + } } // restore state if configured if (isInitialEmit && settings.isRestoreOnBootEnabled) { @@ -117,7 +125,7 @@ constructor( ) @OptIn(ExperimentalCoroutinesApi::class) - override val errorEvents: SharedFlow> = + override val errorEvents: SharedFlow> = tunnelProviderFlow .flatMapLatest { it.errorEvents } .shareIn( diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/TunnelProvider.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/TunnelProvider.kt index 49f19652..c1a58d44 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/TunnelProvider.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/TunnelProvider.kt @@ -2,7 +2,7 @@ package com.zaneschepke.wireguardautotunnel.core.tunnel import com.zaneschepke.wireguardautotunnel.domain.enums.BackendMode import com.zaneschepke.wireguardautotunnel.domain.enums.TunnelStatus -import com.zaneschepke.wireguardautotunnel.domain.events.BackendError +import com.zaneschepke.wireguardautotunnel.domain.events.BackendCoreException import com.zaneschepke.wireguardautotunnel.domain.events.BackendMessage import com.zaneschepke.wireguardautotunnel.domain.model.TunnelConf import com.zaneschepke.wireguardautotunnel.domain.state.PingState @@ -51,7 +51,7 @@ interface TunnelProvider { val activeTunnels: StateFlow> - val errorEvents: SharedFlow> + val errorEvents: SharedFlow> val messageEvents: SharedFlow> diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/UserspaceTunnel.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/UserspaceTunnel.kt index ae541ee4..aa911140 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/UserspaceTunnel.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/UserspaceTunnel.kt @@ -4,7 +4,7 @@ import com.zaneschepke.wireguardautotunnel.core.service.ServiceManager import com.zaneschepke.wireguardautotunnel.data.model.DnsProtocol import com.zaneschepke.wireguardautotunnel.domain.enums.BackendMode import com.zaneschepke.wireguardautotunnel.domain.enums.TunnelStatus -import com.zaneschepke.wireguardautotunnel.domain.events.BackendError +import com.zaneschepke.wireguardautotunnel.domain.events.BackendCoreException import com.zaneschepke.wireguardautotunnel.domain.model.AppProxySettings import com.zaneschepke.wireguardautotunnel.domain.model.TunnelConf import com.zaneschepke.wireguardautotunnel.domain.repository.AppDataRepository @@ -12,7 +12,8 @@ import com.zaneschepke.wireguardautotunnel.domain.state.AmneziaStatistics import com.zaneschepke.wireguardautotunnel.domain.state.TunnelStatistics import com.zaneschepke.wireguardautotunnel.util.extensions.asAmBackendMode import com.zaneschepke.wireguardautotunnel.util.extensions.asBackendMode -import com.zaneschepke.wireguardautotunnel.util.extensions.toBackendError +import com.zaneschepke.wireguardautotunnel.util.extensions.toBackendCoreException +import java.io.IOException import java.util.* import javax.inject.Inject import kotlinx.coroutines.CoroutineScope @@ -90,10 +91,10 @@ constructor( backend.setState(tunnel, Tunnel.State.UP, updatedConfig) } catch (e: BackendException) { Timber.e(e, "Failed to start up backend for tunnel ${tunnel.name}") - throw e.toBackendError() + throw e.toBackendCoreException() } catch (e: IllegalArgumentException) { Timber.e(e, "Failed to start up backend for tunnel ${tunnel.name}") - throw BackendError.Config + throw BackendCoreException.Config } } @@ -103,7 +104,7 @@ constructor( backend.setState(tunnel, Tunnel.State.DOWN, tunnel.toAmConfig()) } catch (e: BackendException) { Timber.e(e, "Failed to stop tunnel ${tunnel.id}") - throw e.toBackendError() + throw e.toBackendCoreException() } } @@ -112,7 +113,10 @@ constructor( try { backend.backendMode = backendMode.asAmBackendMode() } catch (e: BackendException) { - throw e.toBackendError() + throw e.toBackendCoreException() + // TODO this should be mapped to BackendException in the lib + } catch (e: IOException) { + throw BackendCoreException.NotAuthorized } } diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/data/AppDatabase.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/data/AppDatabase.kt index 693dc9e8..e01d9a8a 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/data/AppDatabase.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/data/AppDatabase.kt @@ -12,7 +12,7 @@ import com.zaneschepke.wireguardautotunnel.data.entity.TunnelConfig @Database( entities = [Settings::class, TunnelConfig::class, ProxySettings::class], - version = 20, + version = 21, autoMigrations = [ AutoMigration(from = 1, to = 2), @@ -34,6 +34,7 @@ import com.zaneschepke.wireguardautotunnel.data.entity.TunnelConfig AutoMigration(from = 17, to = 18), AutoMigration(from = 18, to = 19, spec = PingMigration::class), AutoMigration(from = 19, to = 20, spec = ProxyMigration::class), + AutoMigration(from = 20, to = 21, spec = FixProxySettingsMigration::class), ], exportSchema = true, ) @@ -86,3 +87,15 @@ class ProxyMigration : AutoMigrationSpec { db.execSQL("INSERT INTO proxy_settings DEFAULT VALUES") } } + +class FixProxySettingsMigration : AutoMigrationSpec { + override fun onPostMigrate(db: SupportSQLiteDatabase) { + val cursor = db.query("SELECT COUNT(*) FROM proxy_settings") + val count = if (cursor.moveToFirst()) cursor.getInt(0) else 0 + cursor.close() + + if (count == 0) { + db.execSQL("INSERT INTO proxy_settings DEFAULT VALUES") + } + } +} diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/domain/events/BackendError.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/domain/events/BackendCoreException.kt similarity index 65% rename from app/src/main/java/com/zaneschepke/wireguardautotunnel/domain/events/BackendError.kt rename to app/src/main/java/com/zaneschepke/wireguardautotunnel/domain/events/BackendCoreException.kt index 4e00b4eb..78efcfa0 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/domain/events/BackendError.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/domain/events/BackendCoreException.kt @@ -3,24 +3,24 @@ package com.zaneschepke.wireguardautotunnel.domain.events import com.zaneschepke.wireguardautotunnel.R import com.zaneschepke.wireguardautotunnel.util.StringValue -sealed class BackendError : Exception() { - data object DNS : BackendError() +sealed class BackendCoreException : Exception() { + data object DNS : BackendCoreException() - data object Unauthorized : BackendError() + data object Unauthorized : BackendCoreException() - data object Config : BackendError() + data object Config : BackendCoreException() - data object KernelModuleName : BackendError() + data object KernelModuleName : BackendCoreException() - data object NotAuthorized : BackendError() + data object NotAuthorized : BackendCoreException() - data object ServiceNotRunning : BackendError() + data object ServiceNotRunning : BackendCoreException() - data object Unknown : BackendError() + data object Unknown : BackendCoreException() - data object TunnelNameTooLong : BackendError() + data object TunnelNameTooLong : BackendCoreException() - data class BounceFailed(val error: BackendError) : BackendError() + data class BounceFailed(val error: BackendCoreException) : BackendCoreException() fun toStringRes() = when (this) { diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/util/extensions/TunnelExtensions.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/util/extensions/TunnelExtensions.kt index ca7b6e35..e10110f0 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/util/extensions/TunnelExtensions.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/util/extensions/TunnelExtensions.kt @@ -5,7 +5,7 @@ import com.wireguard.android.backend.BackendException import com.zaneschepke.wireguardautotunnel.domain.enums.BackendMode import com.zaneschepke.wireguardautotunnel.domain.enums.HandshakeStatus import com.zaneschepke.wireguardautotunnel.domain.enums.TunnelStatus -import com.zaneschepke.wireguardautotunnel.domain.events.BackendError +import com.zaneschepke.wireguardautotunnel.domain.events.BackendCoreException import com.zaneschepke.wireguardautotunnel.domain.state.TunnelStatistics import com.zaneschepke.wireguardautotunnel.ui.theme.SilverTree import com.zaneschepke.wireguardautotunnel.ui.theme.Straw @@ -96,37 +96,39 @@ fun Tunnel.State.asTunnelState(): TunnelStatus { } } -fun BackendException.toBackendError(): BackendError { +fun BackendException.toBackendCoreException(): BackendCoreException { return when (this.reason) { - BackendException.Reason.VPN_NOT_AUTHORIZED -> BackendError.Unauthorized - BackendException.Reason.DNS_RESOLUTION_FAILURE -> BackendError.DNS - BackendException.Reason.UNKNOWN_KERNEL_MODULE_NAME -> BackendError.KernelModuleName - BackendException.Reason.WG_QUICK_CONFIG_ERROR_CODE -> BackendError.Config - BackendException.Reason.TUNNEL_MISSING_CONFIG -> BackendError.Config - BackendException.Reason.UNABLE_TO_START_VPN -> BackendError.NotAuthorized - BackendException.Reason.TUN_CREATION_ERROR -> BackendError.NotAuthorized - BackendException.Reason.GO_ACTIVATION_ERROR_CODE -> BackendError.Unknown + BackendException.Reason.VPN_NOT_AUTHORIZED -> BackendCoreException.Unauthorized + BackendException.Reason.DNS_RESOLUTION_FAILURE -> BackendCoreException.DNS + BackendException.Reason.UNKNOWN_KERNEL_MODULE_NAME -> BackendCoreException.KernelModuleName + BackendException.Reason.WG_QUICK_CONFIG_ERROR_CODE -> BackendCoreException.Config + BackendException.Reason.TUNNEL_MISSING_CONFIG -> BackendCoreException.Config + BackendException.Reason.UNABLE_TO_START_VPN -> BackendCoreException.NotAuthorized + BackendException.Reason.TUN_CREATION_ERROR -> BackendCoreException.NotAuthorized + BackendException.Reason.GO_ACTIVATION_ERROR_CODE -> BackendCoreException.Unknown } } -fun org.amnezia.awg.backend.BackendException.toBackendError(): BackendError { +fun org.amnezia.awg.backend.BackendException.toBackendCoreException(): BackendCoreException { return when (this.reason) { org.amnezia.awg.backend.BackendException.Reason.VPN_NOT_AUTHORIZED -> - BackendError.Unauthorized - org.amnezia.awg.backend.BackendException.Reason.DNS_RESOLUTION_FAILURE -> BackendError.DNS + BackendCoreException.Unauthorized + org.amnezia.awg.backend.BackendException.Reason.DNS_RESOLUTION_FAILURE -> + BackendCoreException.DNS org.amnezia.awg.backend.BackendException.Reason.UNKNOWN_KERNEL_MODULE_NAME -> - BackendError.KernelModuleName + BackendCoreException.KernelModuleName org.amnezia.awg.backend.BackendException.Reason.AWG_QUICK_CONFIG_ERROR_CODE -> - BackendError.Config - org.amnezia.awg.backend.BackendException.Reason.TUNNEL_MISSING_CONFIG -> BackendError.Config + BackendCoreException.Config + org.amnezia.awg.backend.BackendException.Reason.TUNNEL_MISSING_CONFIG -> + BackendCoreException.Config org.amnezia.awg.backend.BackendException.Reason.UNABLE_TO_START_VPN -> - BackendError.NotAuthorized + BackendCoreException.NotAuthorized org.amnezia.awg.backend.BackendException.Reason.TUN_CREATION_ERROR -> - BackendError.NotAuthorized + BackendCoreException.NotAuthorized org.amnezia.awg.backend.BackendException.Reason.GO_ACTIVATION_ERROR_CODE -> - BackendError.Unknown + BackendCoreException.Unknown org.amnezia.awg.backend.BackendException.Reason.SERVICE_NOT_RUNNING -> - BackendError.ServiceNotRunning + BackendCoreException.ServiceNotRunning } } diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/viewmodel/AppViewModel.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/viewmodel/AppViewModel.kt index 7f2d381b..7554370c 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/viewmodel/AppViewModel.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/viewmodel/AppViewModel.kt @@ -23,7 +23,7 @@ import com.zaneschepke.wireguardautotunnel.di.AppShell import com.zaneschepke.wireguardautotunnel.di.IoDispatcher import com.zaneschepke.wireguardautotunnel.di.MainDispatcher import com.zaneschepke.wireguardautotunnel.domain.enums.ConfigType -import com.zaneschepke.wireguardautotunnel.domain.events.BackendError +import com.zaneschepke.wireguardautotunnel.domain.events.BackendCoreException import com.zaneschepke.wireguardautotunnel.domain.model.AppSettings import com.zaneschepke.wireguardautotunnel.domain.model.AppState import com.zaneschepke.wireguardautotunnel.domain.model.TunnelConf @@ -472,7 +472,7 @@ constructor( tunnelManager.errorEvents.collect { errorEvent -> handleShowMessage( when (val event = errorEvent.second) { - is BackendError.BounceFailed -> event.toStringValue() + is BackendCoreException.BounceFailed -> event.toStringValue() else -> StringValue.StringResource( R.string.tunnel_error_template, diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5599b231..18bb6563 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] accompanist = "0.37.3" activityCompose = "1.10.1" -amneziawgAndroid = "2.0.1" +amneziawgAndroid = "2.0.3" androidx-junit = "1.3.0" icmp4a = "1.0.0" roomdatabasebackup = "1.1.0"