diff --git a/android/src/main/java/com/tailscale/ipn/App.kt b/android/src/main/java/com/tailscale/ipn/App.kt index ce04a46..7c4c97d 100644 --- a/android/src/main/java/com/tailscale/ipn/App.kt +++ b/android/src/main/java/com/tailscale/ipn/App.kt @@ -280,7 +280,7 @@ class App : Application(), libtailscale.AppContext { Runnable { val intent: Intent? = VpnService.prepare(act) if (intent == null) { - Libtailscale.onVPNPrepared() + startVPN() } else { startActivityForResult(act, intent, reqCode) } diff --git a/android/src/main/java/com/tailscale/ipn/IPNService.kt b/android/src/main/java/com/tailscale/ipn/IPNService.kt index 3558286..3a8bce7 100644 --- a/android/src/main/java/com/tailscale/ipn/IPNService.kt +++ b/android/src/main/java/com/tailscale/ipn/IPNService.kt @@ -10,8 +10,8 @@ import android.os.Build import android.system.OsConstants import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat -import java.util.UUID import libtailscale.Libtailscale +import java.util.UUID open class IPNService : VpnService(), libtailscale.IPNService { private val randomID: String = UUID.randomUUID().toString() diff --git a/android/src/main/java/com/tailscale/ipn/MainActivity.kt b/android/src/main/java/com/tailscale/ipn/MainActivity.kt index 76fec34..8f7c07d 100644 --- a/android/src/main/java/com/tailscale/ipn/MainActivity.kt +++ b/android/src/main/java/com/tailscale/ipn/MainActivity.kt @@ -22,6 +22,7 @@ import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController import androidx.navigation.navArgument import androidx.navigation.navigation +import com.tailscale.ipn.Peer.RequestCodes import com.tailscale.ipn.mdm.MDMSettings import com.tailscale.ipn.ui.notifier.Notifier import com.tailscale.ipn.ui.theme.AppTheme @@ -43,12 +44,19 @@ import com.tailscale.ipn.ui.viewModel.SettingsNav import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import com.tailscale.ipn.App class MainActivity : ComponentActivity() { private var notifierScope: CoroutineScope? = null private lateinit var requestVpnPermission: ActivityResultLauncher + companion object { + // Request codes for Android callbacks. + // requestSignin is for Google Sign-In. + @JvmStatic val requestSignin: Int = 1000 + // requestPrepareVPN is for when Android's VpnService.prepare completes. + @JvmStatic val requestPrepareVPN: Int = 1001 + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -107,7 +115,8 @@ class MainActivity : ComponentActivity() { } lifecycleScope.launch { Notifier.readyToPrepareVPN.collect { isReady -> - if (isReady) App.getApplication().prepareVPN(this@MainActivity, -1) + if (isReady) + App.getApplication().prepareVPN(this@MainActivity, RequestCodes.requestPrepareVPN) } } } diff --git a/android/src/main/java/com/tailscale/ipn/Peer.java b/android/src/main/java/com/tailscale/ipn/Peer.java index bf4a647..6fca3f2 100644 --- a/android/src/main/java/com/tailscale/ipn/Peer.java +++ b/android/src/main/java/com/tailscale/ipn/Peer.java @@ -6,11 +6,32 @@ package com.tailscale.ipn; import android.app.Fragment; import android.content.Intent; -import libtailscale.Libtailscale; - public class Peer extends Fragment { + + private static int resultOK = -1; + + public class RequestCodes { + public static final int requestSignin = 1000; + public static final int requestPrepareVPN = 1001; + } + @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { - Libtailscale.onActivityResult(requestCode, resultCode, MaybeGoogle.getIdTokenForActivity(getActivity())); + switch (requestCode) { + case RequestCodes.requestSignin: + if (resultCode != resultOK) { + // TODO: send null Google token + break; + } + // TODO: send Google token + case RequestCodes.requestPrepareVPN: + if (resultCode == resultOK) { + App.getApplication().startVPN(); + } else { + App.getApplication().setWantRunning(false); + // notify VPN revoked + } + + } } } diff --git a/android/src/main/java/com/tailscale/ipn/VPNServiceBuilder.kt b/android/src/main/java/com/tailscale/ipn/VPNServiceBuilder.kt index a2c24be..25abb52 100644 --- a/android/src/main/java/com/tailscale/ipn/VPNServiceBuilder.kt +++ b/android/src/main/java/com/tailscale/ipn/VPNServiceBuilder.kt @@ -27,8 +27,8 @@ class VPNServiceBuilder(private val builder: VpnService.Builder) : libtailscale. return builder.establish()?.let { ParcelFileDescriptor(it) } } - override fun setMTU(p0: Long) { - TODO("Not yet implemented") + override fun setMTU(p0: Int) { + builder.setMtu(p0) } } diff --git a/android/src/main/java/com/tailscale/ipn/ui/notifier/Notifier.kt b/android/src/main/java/com/tailscale/ipn/ui/notifier/Notifier.kt index 9b8babb..63522ed 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/notifier/Notifier.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/notifier/Notifier.kt @@ -69,14 +69,9 @@ object Notifier { notify.LoginFinished?.let { loginFinished.set(it.property) } notify.Version?.let(version::set) } - var previousState: Ipn.State? = null state.collect { currstate -> - readyToPrepareVPN.set( - previousState != null && - previousState!! <= Ipn.State.Stopped && - currstate > Ipn.State.Stopped) + readyToPrepareVPN.set(currstate > Ipn.State.Stopped) tileReady.set(currstate >= Ipn.State.Stopped) - previousState = currstate } Log.d(TAG, "Stopped") } diff --git a/libtailscale/callbacks.go b/libtailscale/callbacks.go index 89873a7..a0728b2 100644 --- a/libtailscale/callbacks.go +++ b/libtailscale/callbacks.go @@ -33,18 +33,6 @@ var ( onDNSConfigChanged = make(chan struct{}, 1) ) -const ( - // Request codes for Android callbacks. - // requestSignin is for Google Sign-In. - requestSignin = 1000 + iota - // requestPrepareVPN is for when Android's VpnService.prepare - // completes. - requestPrepareVPN -) - -// resultOK is Android's Activity.RESULT_OK. -const resultOK = -1 - func OnShareIntent(nfiles int32, types []int32, mimes []string, items []string, names []string, sizes []int) { // TODO(oxtoacart): actually implement this // const ( diff --git a/libtailscale/interfaces.go b/libtailscale/interfaces.go index 7916712..dbf1464 100644 --- a/libtailscale/interfaces.go +++ b/libtailscale/interfaces.go @@ -65,7 +65,7 @@ type IPNService interface { // VPNServiceBuilder corresponds to Android's VpnService.Builder. type VPNServiceBuilder interface { - SetMTU(int) error + SetMTU(int32) error AddDNSServer(string) error AddSearchDomain(string) error AddRoute(string, int32) error @@ -120,10 +120,6 @@ type InputStream interface { // The below are global callbacks that allow the Java application to notify Go // of various state changes. -func OnVPNPrepared() { - notifyVPNPrepared() -} - func RequestVPN(service IPNService) { onVPNRequested <- service } @@ -131,21 +127,3 @@ func RequestVPN(service IPNService) { func ServiceDisconnect(service IPNService) { onDisconnect <- service } - -func OnActivityResult(reqCode, resCode int, idToken string) { - switch reqCode { - case requestSignin: - if resCode != resultOK { - onGoogleToken <- "" - break - } - onGoogleToken <- idToken - case requestPrepareVPN: - if resCode == resultOK { - notifyVPNPrepared() - } else { - notifyVPNClosed() - notifyVPNRevoked() - } - } -}