Skip to content

Commit

Permalink
feat: tunnel on ethernet
Browse files Browse the repository at this point in the history
Adds settings feature to enable auto tunneling on ethernet connections.

Add alphabetical sorting for split tunneling packages

Fix bug where search was not searching by displayed label but by package name

Other refactoring and improvements.

Closes #29 Closes #27 Closes #28
  • Loading branch information
zaneschepke committed Sep 24, 2023
1 parent 1714618 commit 7fbc51a
Show file tree
Hide file tree
Showing 22 changed files with 449 additions and 171 deletions.
4 changes: 2 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ android {
applicationId = "com.zaneschepke.wireguardautotunnel"
minSdk = 26
targetSdk = 34
versionCode = 30000
versionName = "3.0.0"
versionCode = 30001
versionName = "3.0.1"

multiDexEnabled = true

Expand Down
4 changes: 1 addition & 3 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
<action android:name="android.service.quicksettings.action.QS_TILE_PREFERENCES"/>
</intent-filter>
</activity>
<activity
Expand Down Expand Up @@ -117,8 +118,5 @@
</intent-filter>
</receiver>
<receiver android:exported="false" android:name=".receiver.NotificationActionReceiver"/>
<meta-data
android:name="com.google.mlkit.vision.DEPENDENCIES"
android:value="barcode_ui"/>
</application>
</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@ object Constants {
const val VPN_CONNECTIVITY_CHECK_INTERVAL = 3000L
const val VPN_STATISTIC_CHECK_INTERVAL = 10000L
const val SNACKBAR_DELAY = 3000L
const val TOGGLE_TUNNEL_DELAY = 1000L
const val TOGGLE_TUNNEL_DELAY = 500L
const val FADE_IN_ANIMATION_DURATION = 1000
const val SLIDE_IN_ANIMATION_DURATION = 500
const val SLIDE_IN_TRANSITION_OFFSET = 1000
const val VALID_FILE_EXTENSION = ".conf"
const val URI_CONTENT_SCHEME = "content"
const val URI_PACKAGE_SCHEME = "package"
const val ALLOWED_FILE_TYPES = "*/*"
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.zaneschepke.wireguardautotunnel.module

import com.zaneschepke.wireguardautotunnel.service.network.EthernetService
import com.zaneschepke.wireguardautotunnel.service.network.MobileDataService
import com.zaneschepke.wireguardautotunnel.service.network.NetworkService
import com.zaneschepke.wireguardautotunnel.service.network.WifiService
Expand All @@ -26,4 +27,8 @@ abstract class ServiceModule {
@Binds
@ServiceScoped
abstract fun provideMobileDataService(mobileDataService : MobileDataService) : NetworkService<MobileDataService>

@Binds
@ServiceScoped
abstract fun provideEthernetService(ethernetService: EthernetService) : NetworkService<EthernetService>
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class BootReceiver : BroadcastReceiver() {
CoroutineScope(Dispatchers.IO).launch {
try {
val settings = settingsRepo.getAll()
if (!settings.isNullOrEmpty()) {
if (settings.isNotEmpty()) {
val setting = settings.first()
if (setting.isAutoTunnelEnabled && setting.defaultTunnel != null) {
ServiceManager.startWatcherService(context, setting.defaultTunnel!!)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ data class Settings(
@ColumnInfo(name = "trusted_network_ssids") var trustedNetworkSSIDs : MutableList<String> = mutableListOf(),
@ColumnInfo(name = "default_tunnel") var defaultTunnel : String? = null,
@ColumnInfo(name = "is_always_on_vpn_enabled") var isAlwaysOnVpnEnabled : Boolean = false,
@ColumnInfo(name = "is_tunnel_on_ethernet_enabled") var isTunnelOnEthernetEnabled : Boolean = false,
)
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import com.zaneschepke.wireguardautotunnel.Constants
import com.zaneschepke.wireguardautotunnel.R
import com.zaneschepke.wireguardautotunnel.repository.SettingsDoa
import com.zaneschepke.wireguardautotunnel.repository.model.Settings
import com.zaneschepke.wireguardautotunnel.service.network.EthernetService
import com.zaneschepke.wireguardautotunnel.service.network.MobileDataService
import com.zaneschepke.wireguardautotunnel.service.network.NetworkService
import com.zaneschepke.wireguardautotunnel.service.network.NetworkStatus
Expand All @@ -38,6 +39,9 @@ class WireGuardConnectivityWatcherService : ForegroundService() {
@Inject
lateinit var mobileDataService : NetworkService<MobileDataService>

@Inject
lateinit var ethernetService: NetworkService<EthernetService>

@Inject
lateinit var settingsRepo: SettingsDoa

Expand All @@ -48,6 +52,7 @@ class WireGuardConnectivityWatcherService : ForegroundService() {
lateinit var vpnService : VpnService

private var isWifiConnected = false;
private var isEthernetConnected = false;
private var isMobileDataConnected = false;
private var currentNetworkSSID = "";

Expand Down Expand Up @@ -142,6 +147,11 @@ class WireGuardConnectivityWatcherService : ForegroundService() {
watchForMobileDataConnectivityChanges()
}
}
if(setting.isTunnelOnEthernetEnabled) {
launch {
watchForEthernetConnectivityChanges()
}
}
launch {
manageVpn()
}
Expand All @@ -167,6 +177,25 @@ class WireGuardConnectivityWatcherService : ForegroundService() {
}
}

private suspend fun watchForEthernetConnectivityChanges() {
ethernetService.networkStatus.collect {
when (it) {
is NetworkStatus.Available -> {
Timber.d("Gained Ethernet connection")
isEthernetConnected = true
}
is NetworkStatus.CapabilitiesChanged -> {
Timber.d("Ethernet capabilities changed")
isEthernetConnected = true
}
is NetworkStatus.Unavailable -> {
isEthernetConnected = false
Timber.d("Lost Ethernet connection")
}
}
}
}

private suspend fun watchForWifiConnectivityChanges() {
wifiService.networkStatus.collect {
when (it) {
Expand All @@ -189,20 +218,23 @@ class WireGuardConnectivityWatcherService : ForegroundService() {

private suspend fun manageVpn() {
while(true) {
if(setting.isTunnelOnMobileDataEnabled &&
if(isEthernetConnected && setting.isTunnelOnEthernetEnabled && vpnService.getState() == Tunnel.State.DOWN) {
ServiceManager.startVpnService(this, tunnelConfig)
}
if(!isEthernetConnected && setting.isTunnelOnMobileDataEnabled &&
!isWifiConnected &&
isMobileDataConnected
&& vpnService.getState() == Tunnel.State.DOWN) {
ServiceManager.startVpnService(this, tunnelConfig)
} else if(!setting.isTunnelOnMobileDataEnabled &&
} else if(!isEthernetConnected && !setting.isTunnelOnMobileDataEnabled &&
!isWifiConnected &&
vpnService.getState() == Tunnel.State.UP) {
ServiceManager.stopVpnService(this)
} else if(isWifiConnected &&
} else if(!isEthernetConnected && isWifiConnected &&
!setting.trustedNetworkSSIDs.contains(currentNetworkSSID) &&
(vpnService.getState() != Tunnel.State.UP)) {
ServiceManager.startVpnService(this, tunnelConfig)
} else if((isWifiConnected &&
} else if(!isEthernetConnected && (isWifiConnected &&
setting.trustedNetworkSSIDs.contains(currentNetworkSSID)) &&
(vpnService.getState() == Tunnel.State.UP)) {
ServiceManager.stopVpnService(this)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.zaneschepke.wireguardautotunnel.service.network

import android.content.Context
import android.net.NetworkCapabilities
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject

class EthernetService @Inject constructor(@ApplicationContext context: Context) :
BaseNetworkService<EthernetService>(context, NetworkCapabilities.TRANSPORT_ETHERNET) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,11 @@ object ShortcutsManager {
)
}

fun removeTunnelShortcuts(context : Context, tunnelConfig : TunnelConfig) {
ShortcutManagerCompat.removeDynamicShortcuts(context, listOf(tunnelConfig.id.toString() + APPEND_ON,
tunnelConfig.id.toString() + APPEND_OFF ))
fun removeTunnelShortcuts(context : Context, tunnelConfig : TunnelConfig?) {
if(tunnelConfig != null) {
ShortcutManagerCompat.removeDynamicShortcuts(context, listOf(tunnelConfig.id.toString() + APPEND_ON,
tunnelConfig.id.toString() + APPEND_OFF ))
}
}

private fun createTunnelOnIntent(context: Context, extras : Map<String,String>) : Intent {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.zaneschepke.wireguardautotunnel.ui

import com.journeyapps.barcodescanner.CaptureActivity

class CaptureActivityPortrait : CaptureActivity()
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import com.zaneschepke.wireguardautotunnel.ui.screens.settings.SettingsScreen
import com.zaneschepke.wireguardautotunnel.ui.screens.support.SupportScreen
import com.zaneschepke.wireguardautotunnel.ui.theme.TransparentSystemBars
import com.zaneschepke.wireguardautotunnel.ui.theme.WireguardAutoTunnelTheme
import com.zaneschepke.wireguardautotunnel.util.WgTunnelException
import dagger.hilt.android.AndroidEntryPoint
import timber.log.Timber
import java.lang.IllegalStateException
Expand Down Expand Up @@ -101,7 +102,7 @@ class MainActivity : AppCompatActivity() {
}
false
} else -> {
false;
false
}
}
} else {
Expand Down Expand Up @@ -131,8 +132,8 @@ class MainActivity : AppCompatActivity() {
val intentSettings =
Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
intentSettings.data =
Uri.fromParts("package", this.packageName, null)
startActivity(intentSettings);
Uri.fromParts(Constants.URI_PACKAGE_SCHEME, this.packageName, null)
startActivity(intentSettings)
},
message = getString(R.string.notification_permission_required),
getString(R.string.open_settings)
Expand Down Expand Up @@ -190,10 +191,19 @@ class MainActivity : AppCompatActivity() {
}) { SupportScreen(padding = padding, focusRequester) }
composable("${Routes.Config.name}/{id}", enterTransition = {
fadeIn(animationSpec = tween(Constants.FADE_IN_ANIMATION_DURATION))
}) { ConfigScreen(padding = padding, navController = navController, id = it.arguments?.getString("id"), focusRequester = focusRequester)}
}) {
val id = it.arguments?.getString("id")
if(!id.isNullOrBlank()) {
ConfigScreen(padding = padding, navController = navController, id = id, focusRequester = focusRequester)}
}
composable("${Routes.Detail.name}/{id}", enterTransition = {
fadeIn(animationSpec = tween(Constants.FADE_IN_ANIMATION_DURATION))
}) { DetailScreen(padding = padding, id = it.arguments?.getString("id")) }
}) {
val id = it.arguments?.getString("id")
if(!id.isNullOrBlank()) {
DetailScreen(padding = padding, id = id)
}
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
Expand Down Expand Up @@ -53,7 +54,7 @@ fun ConfigScreen(
padding: PaddingValues,
focusRequester: FocusRequester,
navController: NavController,
id : String?
id : String
) {

val context = LocalContext.current
Expand All @@ -67,11 +68,12 @@ fun ConfigScreen(
val checkedPackages by viewModel.checkedPackages.collectAsStateWithLifecycle()
val include by viewModel.include.collectAsStateWithLifecycle()
val allApplications by viewModel.allApplications.collectAsStateWithLifecycle()
val sortedPackages = remember(packages) {
packages.sortedBy { viewModel.getPackageLabel(it) }
}

LaunchedEffect(Unit) {
viewModel.getTunnelById(id)
viewModel.emitQueriedPackages("")
viewModel.emitCurrentPackageConfigurations(id)
viewModel.emitScreenData(id)
}

if(tunnel != null) {
Expand Down Expand Up @@ -174,7 +176,7 @@ fun ConfigScreen(
SearchBar(viewModel::emitQueriedPackages);
}
}
items(packages) { pack ->
items(sortedPackages, key = { it.packageName }) { pack ->
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
Expand All @@ -200,8 +202,7 @@ fun ConfigScreen(
)
}
Text(
pack.applicationInfo.loadLabel(context.packageManager)
.toString(), modifier = Modifier.padding(5.dp)
viewModel.getPackageLabel(pack), modifier = Modifier.padding(5.dp)
)
}
Checkbox(
Expand Down
Loading

0 comments on commit 7fbc51a

Please sign in to comment.