summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArne Schwabe <arne@rfc2549.org>2013-11-19 15:44:06 +0100
committerArne Schwabe <arne@rfc2549.org>2013-11-19 15:44:06 +0100
commit08fcccc93dce0b7ecdb16af3b5fd2585b452aaf1 (patch)
treea7b744693b5b34bd8bfed6416af21bf1c3b56f22
parentbf13e848dc3de1b5cf0143d823f8a86a53ac71b8 (diff)
Android 4.4 workaround,
-rw-r--r--icsopenvpn.iml32
-rw-r--r--src/de/blinkt/openvpn/LogWindow.java9
-rw-r--r--src/de/blinkt/openvpn/api/ExternalOpenVPNService.java498
-rw-r--r--src/de/blinkt/openvpn/core/OpenVPNThread.java3
-rw-r--r--src/de/blinkt/openvpn/core/OpenVpnManagementThread.java11
-rw-r--r--src/de/blinkt/openvpn/core/OpenVpnService.java33
6 files changed, 320 insertions, 266 deletions
diff --git a/icsopenvpn.iml b/icsopenvpn.iml
index 5c38a169..ad327925 100644
--- a/icsopenvpn.iml
+++ b/icsopenvpn.iml
@@ -27,30 +27,31 @@
<sourceFolder url="file://$MODULE_DIR$/build/source/aidl/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/source/rs/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/source/buildConfig/debug" isTestSource="false" generated="true" />
- <sourceFolder url="file://$MODULE_DIR$/build/res/rs/debug" isTestSource="false" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/res/rs/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/source/r/test" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/build/source/aidl/test" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/build/source/rs/test" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/build/source/buildConfig/test" isTestSource="true" />
- <sourceFolder url="file://$MODULE_DIR$/build/res/rs/test" isTestSource="true" />
- <sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" generated="true" />
- <sourceFolder url="file://$MODULE_DIR$/src/debug/assets" isTestSource="false" generated="true" />
- <sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" generated="true" />
- <sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" generated="true" />
- <sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" generated="true" />
- <sourceFolder url="file://$MODULE_DIR$/src/debug/res" isTestSource="false" generated="true" />
- <sourceFolder url="file://$MODULE_DIR$/src/debug/resources" isTestSource="false" generated="true" />
- <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" generated="true" />
- <sourceFolder url="file://$MODULE_DIR$/assets" isTestSource="false" generated="true" />
- <sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" generated="true" />
- <sourceFolder url="file://$MODULE_DIR$/res" isTestSource="false" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/res/rs/test" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/assets" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/assets" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/res" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/instrumentTest/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/instrumentTest/assets" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/instrumentTest/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/instrumentTest/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/instrumentTest/rs" isTestSource="true" />
- <sourceFolder url="file://$MODULE_DIR$/src/instrumentTest/res" isTestSource="true" />
- <sourceFolder url="file://$MODULE_DIR$/src/instrumentTest/resources" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/instrumentTest/res" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/instrumentTest/resources" type="java-test-resource" />
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
<excludeFolder url="file://$MODULE_DIR$/.hg" />
<excludeFolder url="file://$MODULE_DIR$/.hgcheck" />
@@ -64,6 +65,7 @@
<excludeFolder url="file://$MODULE_DIR$/build/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/libs" />
<excludeFolder url="file://$MODULE_DIR$/build/manifests" />
+ <excludeFolder url="file://$MODULE_DIR$/build/res" />
<excludeFolder url="file://$MODULE_DIR$/build/symbols" />
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
</content>
diff --git a/src/de/blinkt/openvpn/LogWindow.java b/src/de/blinkt/openvpn/LogWindow.java
index 82a2f4b6..843f85cc 100644
--- a/src/de/blinkt/openvpn/LogWindow.java
+++ b/src/de/blinkt/openvpn/LogWindow.java
@@ -2,6 +2,7 @@ package de.blinkt.openvpn;
import android.app.Activity;
import android.os.Bundle;
+import android.view.MenuItem;
/**
* Created by arne on 13.10.13.
@@ -11,5 +12,13 @@ public class LogWindow extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.log_window);
+ getActionBar().setDisplayHomeAsUpEnabled(true);
+
+ }
+
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ return super.onOptionsItemSelected(item);
}
}
diff --git a/src/de/blinkt/openvpn/api/ExternalOpenVPNService.java b/src/de/blinkt/openvpn/api/ExternalOpenVPNService.java
index 77374355..34b61325 100644
--- a/src/de/blinkt/openvpn/api/ExternalOpenVPNService.java
+++ b/src/de/blinkt/openvpn/api/ExternalOpenVPNService.java
@@ -35,272 +35,272 @@ import de.blinkt.openvpn.core.VPNLaunchHelper;
public class ExternalOpenVPNService extends Service implements StateListener {
- private static final int SEND_TOALL = 0;
+ private static final int SEND_TOALL = 0;
- final RemoteCallbackList<IOpenVPNStatusCallback> mCallbacks =
- new RemoteCallbackList<IOpenVPNStatusCallback>();
+ final RemoteCallbackList<IOpenVPNStatusCallback> mCallbacks =
+ new RemoteCallbackList<IOpenVPNStatusCallback>();
- private OpenVpnService mService;
- private ExternalAppDatabase mExtAppDb;
+ private OpenVpnService mService;
+ private ExternalAppDatabase mExtAppDb;
- private ServiceConnection mConnection = new ServiceConnection() {
+ private ServiceConnection mConnection = new ServiceConnection() {
- @Override
- public void onServiceConnected(ComponentName className,
- IBinder service) {
- // We've bound to LocalService, cast the IBinder and get LocalService instance
- LocalBinder binder = (LocalBinder) service;
- mService = binder.getService();
- }
+ @Override
+ public void onServiceConnected(ComponentName className,
+ IBinder service) {
+ // We've bound to LocalService, cast the IBinder and get LocalService instance
+ LocalBinder binder = (LocalBinder) service;
+ mService = binder.getService();
+ }
- @Override
- public void onServiceDisconnected(ComponentName arg0) {
- mService =null;
- }
-
- };
-
- @Override
- public void onCreate() {
- super.onCreate();
- VpnStatus.addStateListener(this);
- mExtAppDb = new ExternalAppDatabase(this);
+ @Override
+ public void onServiceDisconnected(ComponentName arg0) {
+ mService = null;
+ }
+
+ };
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ VpnStatus.addStateListener(this);
+ mExtAppDb = new ExternalAppDatabase(this);
- Intent intent = new Intent(getBaseContext(), OpenVpnService.class);
- intent.setAction(OpenVpnService.START_SERVICE);
-
- bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
- mHandler.setService(this);
- }
-
- private final IOpenVPNAPIService.Stub mBinder = new IOpenVPNAPIService.Stub() {
+ Intent intent = new Intent(getBaseContext(), OpenVpnService.class);
+ intent.setAction(OpenVpnService.START_SERVICE);
+
+ bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
+ mHandler.setService(this);
+ }
+
+ private final IOpenVPNAPIService.Stub mBinder = new IOpenVPNAPIService.Stub() {
- private void checkOpenVPNPermission() throws SecurityRemoteException{
- PackageManager pm = getPackageManager();
-
- for (String apppackage:mExtAppDb.getExtAppList()) {
- ApplicationInfo app;
- try {
- app = pm.getApplicationInfo(apppackage, 0);
- if (Binder.getCallingUid() == app.uid) {
- return;
- }
- } catch (NameNotFoundException e) {
- // App not found. Remove it from the list
- mExtAppDb.removeApp(apppackage);
- e.printStackTrace();
- }
+ private void checkOpenVPNPermission() throws SecurityRemoteException {
+ PackageManager pm = getPackageManager();
+
+ for (String apppackage : mExtAppDb.getExtAppList()) {
+ ApplicationInfo app;
+ try {
+ app = pm.getApplicationInfo(apppackage, 0);
+ if (Binder.getCallingUid() == app.uid) {
+ return;
+ }
+ } catch (NameNotFoundException e) {
+ // App not found. Remove it from the list
+ mExtAppDb.removeApp(apppackage);
+ e.printStackTrace();
+ }
- }
- throw new SecurityException("Unauthorized OpenVPN API Caller");
- }
-
- @Override
- public List<APIVpnProfile> getProfiles() throws RemoteException {
- checkOpenVPNPermission();
+ }
+ throw new SecurityException("Unauthorized OpenVPN API Caller");
+ }
+
+ @Override
+ public List<APIVpnProfile> getProfiles() throws RemoteException {
+ checkOpenVPNPermission();
- ProfileManager pm = ProfileManager.getInstance(getBaseContext());
+ ProfileManager pm = ProfileManager.getInstance(getBaseContext());
- List<APIVpnProfile> profiles = new LinkedList<APIVpnProfile>();
+ List<APIVpnProfile> profiles = new LinkedList<APIVpnProfile>();
- for(VpnProfile vp: pm.getProfiles())
- profiles.add(new APIVpnProfile(vp.getUUIDString(),vp.mName,vp.mUserEditable));
+ for (VpnProfile vp : pm.getProfiles())
+ profiles.add(new APIVpnProfile(vp.getUUIDString(), vp.mName, vp.mUserEditable));
- return profiles;
- }
+ return profiles;
+ }
- @Override
- public void startProfile(String profileUUID) throws RemoteException {
- checkOpenVPNPermission();
-
- Intent shortVPNIntent = new Intent(Intent.ACTION_MAIN);
- shortVPNIntent.setClass(getBaseContext(),de.blinkt.openvpn.LaunchVPN.class);
- shortVPNIntent.putExtra(de.blinkt.openvpn.LaunchVPN.EXTRA_KEY,profileUUID);
- shortVPNIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- startActivity(shortVPNIntent);
- }
+ @Override
+ public void startProfile(String profileUUID) throws RemoteException {
+ checkOpenVPNPermission();
+
+ Intent shortVPNIntent = new Intent(Intent.ACTION_MAIN);
+ shortVPNIntent.setClass(getBaseContext(), de.blinkt.openvpn.LaunchVPN.class);
+ shortVPNIntent.putExtra(de.blinkt.openvpn.LaunchVPN.EXTRA_KEY, profileUUID);
+ shortVPNIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(shortVPNIntent);
+ }
- public void startVPN(String inlineconfig) throws RemoteException {
- checkOpenVPNPermission();
+ public void startVPN(String inlineconfig) throws RemoteException {
+ checkOpenVPNPermission();
- ConfigParser cp = new ConfigParser();
- try {
- cp.parseConfig(new StringReader(inlineconfig));
- VpnProfile vp = cp.convertProfile();
- if(vp.checkProfile(getApplicationContext()) != R.string.no_error_found)
- throw new RemoteException(getString(vp.checkProfile(getApplicationContext())));
-
-
- ProfileManager.setTemporaryProfile(vp);
- VPNLaunchHelper.startOpenVpn(vp, getBaseContext());
-
-
- } catch (IOException e) {
- throw new RemoteException(e.getMessage());
- } catch (ConfigParseError e) {
- throw new RemoteException(e.getMessage());
- }
- }
-
- @Override
- public boolean addVPNProfile(String name, String config) throws RemoteException {
- checkOpenVPNPermission();
-
- ConfigParser cp = new ConfigParser();
- try {
- cp.parseConfig(new StringReader(config));
- VpnProfile vp = cp.convertProfile();
- vp.mName = name;
- ProfileManager pm = ProfileManager.getInstance(getBaseContext());
- pm.addProfile(vp);
- } catch (IOException e) {
- e.printStackTrace();
- return false;
- } catch (ConfigParseError e) {
- e.printStackTrace();
- return false;
- }
-
- return true;
- }
-
-
- @Override
- public Intent prepare(String packagename) {
- if (new ExternalAppDatabase(ExternalOpenVPNService.this).isAllowed(packagename))
- return null;
-
- Intent intent = new Intent();
- intent.setClass(ExternalOpenVPNService.this, ConfirmDialog.class);
- return intent;
- }
-
- @Override
- public Intent prepareVPNService() throws RemoteException {
- checkOpenVPNPermission();
-
- if(VpnService.prepare(ExternalOpenVPNService.this)==null)
- return null;
- else
- return new Intent(getBaseContext(), GrantPermissionsActivity.class);
- }
-
-
- @Override
- public void registerStatusCallback(IOpenVPNStatusCallback cb)
- throws RemoteException {
- checkOpenVPNPermission();
-
- if (cb != null) {
- cb.newStatus(mMostRecentState.vpnUUID, mMostRecentState.state,
- mMostRecentState.logmessage, mMostRecentState.level.name());
- mCallbacks.register(cb);
- }
-
-
- }
-
- @Override
- public void unregisterStatusCallback(IOpenVPNStatusCallback cb)
- throws RemoteException {
- checkOpenVPNPermission();
-
- if (cb != null)
- mCallbacks.unregister(cb);
- }
-
- @Override
- public void disconnect() throws RemoteException {
- checkOpenVPNPermission();
- if(mService!=null && mService.getManagement()!=null)
- mService.getManagement().stopVPN();
- }
- };
-
-
-
- private UpdateMessage mMostRecentState; @Override
- public IBinder onBind(Intent intent) {
- return mBinder;
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- mCallbacks.kill();
- unbindService(mConnection);
- VpnStatus.removeStateListener(this);
- }
-
- class UpdateMessage {
- public String state;
- public String logmessage;
- public ConnectionStatus level;
- public String vpnUUID;
-
- public UpdateMessage(String state, String logmessage, ConnectionStatus level) {
- this.state = state;
- this.logmessage = logmessage;
- this.level = level;
- }
- }
-
- @Override
- public void updateState (String state, String logmessage, int resid, ConnectionStatus level) {
- mMostRecentState = new UpdateMessage(state, logmessage, level);
- if (ProfileManager.getLastConnectedVpn()!=null)
- mMostRecentState.vpnUUID = ProfileManager.getLastConnectedVpn().getUUIDString();
-
- Message msg = mHandler.obtainMessage(SEND_TOALL, mMostRecentState);
- msg.sendToTarget();
-
- }
-
- private static final OpenVPNServiceHandler mHandler = new OpenVPNServiceHandler();
-
-
- static class OpenVPNServiceHandler extends Handler {
- WeakReference<ExternalOpenVPNService> service= null;
-
- private void setService(ExternalOpenVPNService eos)
- {
- service = new WeakReference<ExternalOpenVPNService>(eos);
- }
-
- @Override public void handleMessage(Message msg) {
-
- RemoteCallbackList<IOpenVPNStatusCallback> callbacks;
- switch (msg.what) {
- case SEND_TOALL:
- if(service ==null || service.get() == null)
- return;
-
- callbacks = service.get().mCallbacks;
-
-
- // Broadcast to all clients the new value.
- final int N = callbacks.beginBroadcast();
- for (int i=0; i<N; i++) {
- try {
- sendUpdate(callbacks.getBroadcastItem(i),(UpdateMessage) msg.obj);
- } catch (RemoteException e) {
- // The RemoteCallbackList will take care of removing
- // the dead object for us.
- }
- }
- callbacks.finishBroadcast();
- break;
- }
- }
-
- private void sendUpdate(IOpenVPNStatusCallback broadcastItem,
- UpdateMessage um) throws RemoteException
- {
- broadcastItem.newStatus(um.vpnUUID, um.state, um.logmessage, um.level.name());
- }
- }
+ ConfigParser cp = new ConfigParser();
+ try {
+ cp.parseConfig(new StringReader(inlineconfig));
+ VpnProfile vp = cp.convertProfile();
+ if (vp.checkProfile(getApplicationContext()) != R.string.no_error_found)
+ throw new RemoteException(getString(vp.checkProfile(getApplicationContext())));
+
+
+ ProfileManager.setTemporaryProfile(vp);
+ VPNLaunchHelper.startOpenVpn(vp, getBaseContext());
+
+
+ } catch (IOException e) {
+ throw new RemoteException(e.getMessage());
+ } catch (ConfigParseError e) {
+ throw new RemoteException(e.getMessage());
+ }
+ }
+
+ @Override
+ public boolean addVPNProfile(String name, String config) throws RemoteException {
+ checkOpenVPNPermission();
+
+ ConfigParser cp = new ConfigParser();
+ try {
+ cp.parseConfig(new StringReader(config));
+ VpnProfile vp = cp.convertProfile();
+ vp.mName = name;
+ ProfileManager pm = ProfileManager.getInstance(getBaseContext());
+ pm.addProfile(vp);
+ } catch (IOException e) {
+ e.printStackTrace();
+ return false;
+ } catch (ConfigParseError e) {
+ e.printStackTrace();
+ return false;
+ }
+
+ return true;
+ }
+
+
+ @Override
+ public Intent prepare(String packagename) {
+ if (new ExternalAppDatabase(ExternalOpenVPNService.this).isAllowed(packagename))
+ return null;
+
+ Intent intent = new Intent();
+ intent.setClass(ExternalOpenVPNService.this, ConfirmDialog.class);
+ return intent;
+ }
+
+ @Override
+ public Intent prepareVPNService() throws RemoteException {
+ checkOpenVPNPermission();
+
+ if (VpnService.prepare(ExternalOpenVPNService.this) == null)
+ return null;
+ else
+ return new Intent(getBaseContext(), GrantPermissionsActivity.class);
+ }
+
+
+ @Override
+ public void registerStatusCallback(IOpenVPNStatusCallback cb)
+ throws RemoteException {
+ checkOpenVPNPermission();
+
+ if (cb != null) {
+ cb.newStatus(mMostRecentState.vpnUUID, mMostRecentState.state,
+ mMostRecentState.logmessage, mMostRecentState.level.name());
+ mCallbacks.register(cb);
+ }
+
+
+ }
+
+ @Override
+ public void unregisterStatusCallback(IOpenVPNStatusCallback cb)
+ throws RemoteException {
+ checkOpenVPNPermission();
+
+ if (cb != null)
+ mCallbacks.unregister(cb);
+ }
+
+ @Override
+ public void disconnect() throws RemoteException {
+ checkOpenVPNPermission();
+ if (mService != null && mService.getManagement() != null)
+ mService.getManagement().stopVPN();
+ }
+ };
+
+
+ private UpdateMessage mMostRecentState;
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mBinder;
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ mCallbacks.kill();
+ unbindService(mConnection);
+ VpnStatus.removeStateListener(this);
+ }
+
+ class UpdateMessage {
+ public String state;
+ public String logmessage;
+ public ConnectionStatus level;
+ public String vpnUUID;
+
+ public UpdateMessage(String state, String logmessage, ConnectionStatus level) {
+ this.state = state;
+ this.logmessage = logmessage;
+ this.level = level;
+ }
+ }
+
+ @Override
+ public void updateState(String state, String logmessage, int resid, ConnectionStatus level) {
+ mMostRecentState = new UpdateMessage(state, logmessage, level);
+ if (ProfileManager.getLastConnectedVpn() != null)
+ mMostRecentState.vpnUUID = ProfileManager.getLastConnectedVpn().getUUIDString();
+
+ Message msg = mHandler.obtainMessage(SEND_TOALL, mMostRecentState);
+ msg.sendToTarget();
+
+ }
+
+ private static final OpenVPNServiceHandler mHandler = new OpenVPNServiceHandler();
+
+
+ static class OpenVPNServiceHandler extends Handler {
+ WeakReference<ExternalOpenVPNService> service = null;
+
+ private void setService(ExternalOpenVPNService eos) {
+ service = new WeakReference<ExternalOpenVPNService>(eos);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+
+ RemoteCallbackList<IOpenVPNStatusCallback> callbacks;
+ switch (msg.what) {
+ case SEND_TOALL:
+ if (service == null || service.get() == null)
+ return;
+
+ callbacks = service.get().mCallbacks;
+
+
+ // Broadcast to all clients the new value.
+ final int N = callbacks.beginBroadcast();
+ for (int i = 0; i < N; i++) {
+ try {
+ sendUpdate(callbacks.getBroadcastItem(i), (UpdateMessage) msg.obj);
+ } catch (RemoteException e) {
+ // The RemoteCallbackList will take care of removing
+ // the dead object for us.
+ }
+ }
+ callbacks.finishBroadcast();
+ break;
+ }
+ }
+
+ private void sendUpdate(IOpenVPNStatusCallback broadcastItem,
+ UpdateMessage um) throws RemoteException {
+ broadcastItem.newStatus(um.vpnUUID, um.state, um.logmessage, um.level.name());
+ }
+ }
} \ No newline at end of file
diff --git a/src/de/blinkt/openvpn/core/OpenVPNThread.java b/src/de/blinkt/openvpn/core/OpenVPNThread.java
index 0807b33d..f814ff29 100644
--- a/src/de/blinkt/openvpn/core/OpenVPNThread.java
+++ b/src/de/blinkt/openvpn/core/OpenVPNThread.java
@@ -137,6 +137,9 @@ public class OpenVPNThread implements Runnable {
else if ((flags & M_DEBUG)!=0)
logStatus = VpnStatus.LogLevel.VERBOSE;
+ if (msg.startsWith("MANAGEMENT: CMD"))
+ logLevel = Math.max(4, logLevel);
+
VpnStatus.logMessageOpenVPN(logStatus,logLevel,msg);
} else {
diff --git a/src/de/blinkt/openvpn/core/OpenVpnManagementThread.java b/src/de/blinkt/openvpn/core/OpenVpnManagementThread.java
index 03b36144..abca275a 100644
--- a/src/de/blinkt/openvpn/core/OpenVpnManagementThread.java
+++ b/src/de/blinkt/openvpn/core/OpenVpnManagementThread.java
@@ -273,8 +273,12 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement {
}
int ovpnlevel = Integer.parseInt(args[2]) & 0x0F;
+ String msg = args[3];
- VpnStatus.logMessageOpenVPN(level,ovpnlevel, args[3]);
+ if (msg.startsWith("MANAGEMENT: CMD"))
+ ovpnlevel = Math.max(4, ovpnlevel);
+
+ VpnStatus.logMessageOpenVPN(level,ovpnlevel, msg);
}
private void handleHold() {
@@ -387,7 +391,10 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement {
} else if (needed.equals("IFCONFIG6")) {
mOpenVPNService.setLocalIPv6(extra);
- } else if (needed.equals("OPENTUN")) {
+ } else if (needed.equals("PERSIST_TUN_ACTION")) {
+ // check if tun cfg stayed the same
+ status = mOpenVPNService.getTunReopenStatus();
+ } else if (needed.equals("OPENTUN")) {
if(sendTunFD(needed,extra))
return;
else
diff --git a/src/de/blinkt/openvpn/core/OpenVpnService.java b/src/de/blinkt/openvpn/core/OpenVpnService.java
index e4437d2c..ab21fc1b 100644
--- a/src/de/blinkt/openvpn/core/OpenVpnService.java
+++ b/src/de/blinkt/openvpn/core/OpenVpnService.java
@@ -14,6 +14,7 @@ import android.net.VpnService;
import android.os.*;
import android.os.Handler.Callback;
import android.preference.PreferenceManager;
+import android.text.TextUtils;
import de.blinkt.openvpn.DisconnectVPN;
import de.blinkt.openvpn.LogWindow;
import de.blinkt.openvpn.R;
@@ -24,6 +25,7 @@ import de.blinkt.openvpn.core.VpnStatus.StateListener;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.security.MessageDigest;
import java.util.HashMap;
import java.util.Locale;
import java.util.Vector;
@@ -55,6 +57,7 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac
private long mConnecttime;
private boolean mOvpn3 = false;
private OpenVPNManagement mManagement;
+ private String mLastTunCfg;
// From: http://stackoverflow.com/questions/3758606/how-to-convert-byte-size-into-human-readable-format-in-java
public static String humanReadableByteCount(long bytes, boolean mbit) {
@@ -386,6 +389,24 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac
}
+ private String getTunConfigString()
+ {
+ // The format of the string is not important, only that
+ // two identical configurations produce the same result
+ String cfg="TUNCFG UNQIUE STRING ips:";
+
+ if (mLocalIP!=null)
+ cfg+=mLocalIP.toString();
+ if (mLocalIPv6!=null)
+ cfg+=mLocalIPv6.toString();
+
+ cfg+= "routes: " + TextUtils.join("|",mRoutes) + TextUtils.join("|",mRoutesv6);
+ cfg+= "dns: " + TextUtils.join("|",mDnslist);
+ cfg+= "domain: " + mDomain;
+ cfg+= "mtu: " + mMtu;
+ return cfg;
+ }
+
public ParcelFileDescriptor openTun() {
Builder builder = new Builder();
@@ -465,6 +486,8 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac
if (mDnslist.size() == 0)
VpnStatus.logInfo(R.string.warn_no_dns);
+ mLastTunCfg = getTunConfigString();
+
// Reset information
mDnslist.clear();
mRoutes.clear();
@@ -625,6 +648,16 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac
return mManagement;
}
+ public String getTunReopenStatus() {
+ String currentConfiguration = getTunConfigString();
+ if(currentConfiguration.equals(mLastTunCfg))
+ return "NOACTION";
+ else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
+ return "OPEN_AFTER_CLOSE";
+ else
+ return "OPEN_BEFORE_CLOSE";
+ }
+
public class LocalBinder extends Binder {
public OpenVpnService getService() {
// Return this instance of LocalService so clients can call public methods