From 5c8c5ad6c3c7ee0be5336e5fcf69c6f6dbb91dae Mon Sep 17 00:00:00 2001 From: Arne Schwabe Date: Mon, 10 Aug 2015 13:52:11 +0200 Subject: Ignore short network losses and do not reconnect --- main/build.gradle | 4 +- main/openvpn | 2 +- .../blinkt/openvpn/core/DeviceStateReceiver.java | 67 ++++++++++++++++++---- .../de/blinkt/openvpn/core/OpenVPNManagement.java | 2 +- .../openvpn/core/OpenVpnManagementThread.java | 13 +++-- 5 files changed, 69 insertions(+), 19 deletions(-) diff --git a/main/build.gradle b/main/build.gradle index 041b556a..077ee3a3 100644 --- a/main/build.gradle +++ b/main/build.gradle @@ -18,8 +18,8 @@ android { defaultConfig { minSdkVersion 14 targetSdkVersion 22 - versionCode = 113 - versionName = "0.6.32" + versionCode = 114 + versionName = "0.6.33" } sourceSets { diff --git a/main/openvpn b/main/openvpn index cfb84bf7..0a099916 160000 --- a/main/openvpn +++ b/main/openvpn @@ -1 +1 @@ -Subproject commit cfb84bf7dbf75bcd45069681a9069f9d83bb75d8 +Subproject commit 0a099916c3c7148146761595c14ab643b7250034 diff --git a/main/src/main/java/de/blinkt/openvpn/core/DeviceStateReceiver.java b/main/src/main/java/de/blinkt/openvpn/core/DeviceStateReceiver.java index 9feedf63..240e9e32 100644 --- a/main/src/main/java/de/blinkt/openvpn/core/DeviceStateReceiver.java +++ b/main/src/main/java/de/blinkt/openvpn/core/DeviceStateReceiver.java @@ -12,15 +12,19 @@ import android.content.SharedPreferences; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.NetworkInfo.State; +import android.os.Handler; import android.preference.PreferenceManager; + import de.blinkt.openvpn.R; import de.blinkt.openvpn.core.VpnStatus.ByteCountListener; import java.util.LinkedList; +import java.util.Objects; import static de.blinkt.openvpn.core.OpenVPNManagement.pauseReason; public class DeviceStateReceiver extends BroadcastReceiver implements ByteCountListener { + private final Handler mDisconnectHandler; private int lastNetwork = -1; private OpenVPNManagement mManagement; @@ -29,12 +33,31 @@ public class DeviceStateReceiver extends BroadcastReceiver implements ByteCountL // Data traffic limit in bytes private final long TRAFFIC_LIMIT = 64 * 1024; + // Time to wait after network disconnect to pause the VPN + private final int DISCONNECT_WAIT = 20; + connectState network = connectState.DISCONNECTED; connectState screen = connectState.SHOULDBECONNECTED; connectState userpause = connectState.SHOULDBECONNECTED; private String lastStateMsg = null; + private java.lang.Runnable mDelayDisconnectRunnable = new Runnable() { + @Override + public void run() { + if (!(network == connectState.PENDINGDISCONNECT)) + return; + + network = connectState.DISCONNECTED; + + // Set screen state to be disconnected if disconnect pending + if (screen == connectState.PENDINGDISCONNECT) + screen = connectState.DISCONNECTED; + + mManagement.pause(getPauseReason()); + } + }; + private NetworkInfo lastConnectedNetwork; enum connectState { SHOULDBECONNECTED, @@ -54,6 +77,7 @@ public class DeviceStateReceiver extends BroadcastReceiver implements ByteCountL LinkedList trafficdata = new LinkedList(); + @Override public void updateByteCount(long in, long out, long diffIn, long diffOut) { if (screen != connectState.PENDINGDISCONNECT) @@ -99,6 +123,7 @@ public class DeviceStateReceiver extends BroadcastReceiver implements ByteCountL public DeviceStateReceiver(OpenVPNManagement magnagement) { super(); mManagement = magnagement; + mDisconnectHandler = new Handler(); } @@ -113,7 +138,7 @@ public class DeviceStateReceiver extends BroadcastReceiver implements ByteCountL boolean screenOffPause = prefs.getBoolean("screenoff", false); if (screenOffPause) { - if (ProfileManager.getLastConnectedVpn()!=null && !ProfileManager.getLastConnectedVpn().mPersistTun) + if (ProfileManager.getLastConnectedVpn() != null && !ProfileManager.getLastConnectedVpn().mPersistTun) VpnStatus.logError(R.string.screen_nopersistenttun); screen = connectState.PENDINGDISCONNECT; @@ -126,6 +151,8 @@ public class DeviceStateReceiver extends BroadcastReceiver implements ByteCountL boolean connected = shouldBeConnected(); screen = connectState.SHOULDBECONNECTED; + /* We should connect now, cancel any outstanding disconnect timer */ + mDisconnectHandler.removeCallbacks(mDelayDisconnectRunnable); /* should be connected has changed because the screen is on now, connect the VPN */ if (shouldBeConnected() != connected) mManagement.resume(); @@ -140,6 +167,10 @@ public class DeviceStateReceiver extends BroadcastReceiver implements ByteCountL private void fillTrafficData() { trafficdata.add(new Datapoint(System.currentTimeMillis(), TRAFFIC_LIMIT)); } + public static boolean equalsObj(Object a, Object b) { + return (a == null) ? (b == null) : a.equals(b); + } + public void networkStateChange(Context context) { @@ -175,34 +206,49 @@ public class DeviceStateReceiver extends BroadcastReceiver implements ByteCountL if (networkInfo != null && networkInfo.getState() == State.CONNECTED) { int newnet = networkInfo.getType(); + + boolean pendingDisconnect = (network == connectState.PENDINGDISCONNECT); network = connectState.SHOULDBECONNECTED; - if (lastNetwork != newnet) { + boolean sameNetwork; + if (lastConnectedNetwork == null + || lastConnectedNetwork.getType() != networkInfo.getType() + || !equalsObj(lastConnectedNetwork.getExtraInfo(), networkInfo.getExtraInfo()) + ) + sameNetwork = false; + else + sameNetwork = true; + + if (pendingDisconnect && sameNetwork) { + mDisconnectHandler.removeCallbacks(mDelayDisconnectRunnable); + // Reprotect the sockets just be sure + mManagement.networkChange(true); + } + + if (!sameNetwork) { if (screen == connectState.PENDINGDISCONNECT) screen = connectState.DISCONNECTED; if (shouldBeConnected()) { - if (lastNetwork == -1) { + mDisconnectHandler.removeCallbacks(mDelayDisconnectRunnable); + if (lastNetwork == -1 && !pendingDisconnect) { mManagement.resume(); } else { - mManagement.networkChange(); + mManagement.networkChange(false); } } lastNetwork = newnet; + lastConnectedNetwork = networkInfo; } } else if (networkInfo == null) { // Not connected, stop openvpn, set last connected network to no network lastNetwork = -1; if (sendusr1) { - network = connectState.DISCONNECTED; + network = connectState.PENDINGDISCONNECT; + mDisconnectHandler.postDelayed(mDelayDisconnectRunnable, DISCONNECT_WAIT * 1000); - // Set screen state to be disconnected if disconnect pending - if (screen == connectState.PENDINGDISCONNECT) - screen = connectState.DISCONNECTED; - - mManagement.pause(getPauseReason()); } } @@ -213,6 +259,7 @@ public class DeviceStateReceiver extends BroadcastReceiver implements ByteCountL } + public boolean isUserPaused() { return userpause == connectState.DISCONNECTED; } diff --git a/main/src/main/java/de/blinkt/openvpn/core/OpenVPNManagement.java b/main/src/main/java/de/blinkt/openvpn/core/OpenVPNManagement.java index 1f28c77d..d7666933 100644 --- a/main/src/main/java/de/blinkt/openvpn/core/OpenVPNManagement.java +++ b/main/src/main/java/de/blinkt/openvpn/core/OpenVPNManagement.java @@ -25,5 +25,5 @@ public interface OpenVPNManagement { /* * Rebind the interface */ - void networkChange(); + void networkChange(boolean sameNetwork); } diff --git a/main/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java b/main/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java index da249cc4..e27feab0 100644 --- a/main/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java +++ b/main/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java @@ -12,7 +12,7 @@ import android.net.LocalSocket; import android.net.LocalSocketAddress; import android.os.ParcelFileDescriptor; import android.preference.PreferenceManager; -import android.support.annotation.NonNull; +import android.support.annotation.NonNull; import android.util.Log; import junit.framework.Assert; @@ -64,7 +64,7 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { } - public boolean openManagementInterface(@NonNull Context c) { + public boolean openManagementInterface(@NonNull Context c) { // Could take a while to open connection int tries = 8; @@ -248,7 +248,7 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { Log.i(TAG, "Got unrecognized command" + command); } } else if (command.startsWith("SUCCESS:")) { - /* Ignore this kind of message too */ + /* Ignore this kind of message too */ return; } else if (command.startsWith("PROTECTFD: ")) { FileDescriptor fdtoprotect = mFDList.pollFirst(); @@ -558,9 +558,12 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { } @Override - public void networkChange() { + public void networkChange(boolean samenetwork) { if (!mWaitingForRelease) - managmentCommand("network-change\n"); + if (samenetwork) + managmentCommand("network-change samenetwork\n"); + else + managmentCommand("network-change\n"); } public void signalusr1() { -- cgit v1.2.3