summaryrefslogtreecommitdiff
path: root/src/de/blinkt/openvpn/OpenVpnService.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/de/blinkt/openvpn/OpenVpnService.java')
-rw-r--r--src/de/blinkt/openvpn/OpenVpnService.java236
1 files changed, 178 insertions, 58 deletions
diff --git a/src/de/blinkt/openvpn/OpenVpnService.java b/src/de/blinkt/openvpn/OpenVpnService.java
index 4dff943b..ce9f75a1 100644
--- a/src/de/blinkt/openvpn/OpenVpnService.java
+++ b/src/de/blinkt/openvpn/OpenVpnService.java
@@ -14,11 +14,10 @@
* limitations under the License.
*/
-package de.blinkt.openvpn;
-
-import java.io.IOException;
+package de.blinkt.openvpn;import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.util.Locale;
import java.util.Vector;
import android.annotation.TargetApi;
@@ -28,22 +27,27 @@ import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.LocalServerSocket;
import android.net.LocalSocket;
import android.net.LocalSocketAddress;
import android.net.VpnService;
import android.os.Binder;
-import android.os.Handler;
-import android.os.Handler.Callback;
import android.os.Build;
+import android.os.Handler.Callback;
import android.os.IBinder;
import android.os.Message;
import android.os.ParcelFileDescriptor;
+import android.preference.PreferenceManager;
+import de.blinkt.openvpn.OpenVPN.ByteCountListener;
import de.blinkt.openvpn.OpenVPN.StateListener;
-public class OpenVpnService extends VpnService implements StateListener, Callback {
+public class OpenVpnService extends VpnService implements StateListener, Callback, ByteCountListener {
public static final String START_SERVICE = "de.blinkt.openvpn.START_SERVICE";
+ public static final String START_SERVICE_STICKY = "de.blinkt.openvpn.START_SERVICE_STICKY";
+ public static final String ALWAYS_SHOW_NOTIFICATION = "de.blinkt.openvpn.NOTIFICATION_ALWAYS_VISIBLE";
+
private Thread mProcessThread=null;
@@ -58,9 +62,6 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac
private CIDRIP mLocalIP=null;
- private OpenVpnManagementThread mSocketManager;
-
- private Thread mSocketManagerThread;
private int mMtu;
private String mLocalIPv6=null;
private NetworkSateReceiver mNetworkStateReceiver;
@@ -76,15 +77,25 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac
public static final int PROTECT_FD = 0;
+
+ private static final int LEVEL_OFFLINE = 0;
+ private static final int LEVEL_NOTCONNECTED = 1;
+ private static final int LEVEL_CONNECTED = 2;
+
+ private static boolean mNotificationalwaysVisible=false;
+
private final IBinder mBinder = new LocalBinder();
-
+ private boolean mOvpn3;
+ private Thread mSocketManagerThread;
+ private OpenVPNMangement mManagement;
+
public class LocalBinder extends Binder {
public OpenVpnService getService() {
- // Return this instance of LocalService so clients can call public methods
- return OpenVpnService.this;
- }
- }
-
+ // Return this instance of LocalService so clients can call public methods
+ return OpenVpnService.this;
+ }
+ }
+
@Override
public IBinder onBind(Intent intent) {
String action = intent.getAction();
@@ -93,10 +104,10 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac
else
return super.onBind(intent);
}
-
+
@Override
public void onRevoke() {
- OpenVpnManagementThread.stopOpenVPN();
+ mManagement.stopVPN();
endVpnService();
}
@@ -108,34 +119,43 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac
private void endVpnService() {
mProcessThread=null;
OpenVPN.logBuilderConfig(null);
+ OpenVPN.removeStateListener(this);
+ OpenVPN.removeByteCountListener(this);
+ unregisterNetworkStateReceiver();
ProfileManager.setConntectedVpnProfileDisconnected(this);
if(!mStarting) {
- stopSelf();
- stopForeground(true);
+ stopForeground(!mNotificationalwaysVisible);
+
+ if( !mNotificationalwaysVisible)
+ stopSelf();
}
}
- private void showNotification(String msg, String tickerText, boolean lowpriority, long when) {
+ private void showNotification(String msg, String tickerText, boolean lowpriority, long when, int level) {
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);
- int icon = R.drawable.ic_stat_vpn;
+ int icon = R.drawable.notification_icon;
android.app.Notification.Builder nbuilder = new Notification.Builder(this);
- nbuilder.setContentTitle(getString(R.string.notifcation_title,mProfile.mName));
+ if(mProfile!=null)
+ nbuilder.setContentTitle(getString(R.string.notifcation_title,mProfile.mName));
+ else
+ nbuilder.setContentTitle(getString(R.string.notifcation_title_notconnect));
+
nbuilder.setContentText(msg);
nbuilder.setOnlyAlertOnce(true);
nbuilder.setOngoing(true);
nbuilder.setContentIntent(getLogPendingIntent());
- nbuilder.setSmallIcon(icon);
+ nbuilder.setSmallIcon(icon,level);
if(when !=0)
nbuilder.setWhen(when);
// Try to set the priority available since API 16 (Jellybean)
jbNotificationExtras(lowpriority, nbuilder);
- if(tickerText!=null)
+ if(tickerText!=null && !tickerText.equals(""))
nbuilder.setTicker(tickerText);
@SuppressWarnings("deprecation")
@@ -146,6 +166,7 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac
startForeground(OPENVPN_STATUS, notification);
}
+
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private void jbNotificationExtras(boolean lowpriority,
android.app.Notification.Builder nbuilder) {
@@ -155,7 +176,9 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac
// PRIORITY_MIN == -2
setpriority.invoke(nbuilder, -2 );
- nbuilder.setUsesChronometer(true);
+ Method setUsesChronometer = nbuilder.getClass().getMethod("setUsesChronometer", boolean.class);
+ setUsesChronometer.invoke(nbuilder,true);
+
/* PendingIntent cancelconnet=null;
nbuilder.addAction(android.R.drawable.ic_menu_close_clear_cancel,
@@ -185,6 +208,8 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac
private LocalServerSocket openManagmentInterface(int tries) {
// Could take a while to open connection
String socketname = (getCacheDir().getAbsolutePath() + "/" + "mgmtsocket");
+ // The sock is transfered to the LocalServerSocket, ignore warning
+ @SuppressWarnings("resource")
LocalSocket sock = new LocalSocket();
while(tries > 0 && !sock.isConnected()) {
@@ -211,20 +236,35 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac
}
- void registerNetworkStateReceiver() {
+ void registerNetworkStateReceiver(OpenVPNMangement magnagement) {
// Registers BroadcastReceiver to track network connection changes.
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
- mNetworkStateReceiver = new NetworkSateReceiver(mSocketManager);
+ mNetworkStateReceiver = new NetworkSateReceiver(magnagement);
this.registerReceiver(mNetworkStateReceiver, filter);
}
-
+ void unregisterNetworkStateReceiver() {
+ if(mNetworkStateReceiver!=null)
+ this.unregisterReceiver(mNetworkStateReceiver);
+ mNetworkStateReceiver=null;
+ }
+
+
@Override
- public int onStartCommand(Intent intent, int flags, int startId) {
-
+ public int onStartCommand(Intent intent, int flags, int startId) {
+
+ if(intent != null && intent.getBooleanExtra(ALWAYS_SHOW_NOTIFICATION, false))
+ mNotificationalwaysVisible=true;
+
+ OpenVPN.addStateListener(this);
+ OpenVPN.addByteCountListener(this);
+
if(intent != null && intent.getAction() !=null &&intent.getAction().equals(START_SERVICE))
return START_NOT_STICKY;
-
+ if(intent != null && intent.getAction() !=null &&intent.getAction().equals(START_SERVICE_STICKY)) {
+ return START_REDELIVER_INTENT;
+ }
+
// Extract information from the intent.
String prefix = getPackageName();
@@ -234,21 +274,18 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac
mProfile = ProfileManager.get(profileUUID);
- showNotification("Starting VPN " + mProfile.mName,"Starting VPN " + mProfile.mName, false,0);
-
-
- OpenVPN.addStateListener(this);
+ showNotification("Starting VPN " + mProfile.mName,"Starting VPN " + mProfile.mName, false,0,LEVEL_NOTCONNECTED);
// Set a flag that we are starting a new VPN
mStarting=true;
// Stop the previous session by interrupting the thread.
- if(OpenVpnManagementThread.stopOpenVPN()){
- // an old was asked to exit, wait 2s
+ if(mManagement!=null && mManagement.stopVPN())
+ // an old was asked to exit, wait 1s
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
- }
+
if (mProcessThread!=null) {
mProcessThread.interrupt();
@@ -262,33 +299,72 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac
// Open the Management Interface
- LocalServerSocket mgmtsocket = openManagmentInterface(8);
-
- if(mgmtsocket!=null) {
- // start a Thread that handles incoming messages of the managment socket
- mSocketManager = new OpenVpnManagementThread(mProfile,mgmtsocket,this);
- mSocketManagerThread = new Thread(mSocketManager,"OpenVPNMgmtThread");
- mSocketManagerThread.start();
- OpenVPN.logInfo("started Socket Thread");
- registerNetworkStateReceiver();
+ if(!mOvpn3) {
+ LocalServerSocket mgmtsocket = openManagmentInterface(8);
+
+ if(mgmtsocket!=null) {
+ // start a Thread that handles incoming messages of the managment socket
+ OpenVpnManagementThread ovpnmgmthread = new OpenVpnManagementThread(mProfile,mgmtsocket,this);
+ mSocketManagerThread = new Thread(ovpnmgmthread,"OpenVPNMgmtThread");
+ mSocketManagerThread.start();
+ mManagement= ovpnmgmthread;
+ OpenVPN.logInfo("started Socket Thread");
+ }
}
-
// Start a new session by creating a new thread.
- OpenVPNThread processThread = new OpenVPNThread(this, argv,nativelibdir);
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+
+ mOvpn3 = prefs.getBoolean("ovpn3", false);
+
+ Runnable processThread;
+ if(mOvpn3) {
+
+ OpenVPNMangement mOpenVPN3 = instantiateOpenVPN3Core();
+ processThread = (Runnable) mOpenVPN3;
+ mManagement = mOpenVPN3;
+
+
+ } else {
+ processThread = new OpenVPNThread(this, argv,nativelibdir);
+ }
mProcessThread = new Thread(processThread, "OpenVPNProcessThread");
mProcessThread.start();
+ registerNetworkStateReceiver(mManagement);
+
+
ProfileManager.setConnectedVpnProfile(this, mProfile);
return START_NOT_STICKY;
}
+ private OpenVPNMangement instantiateOpenVPN3Core() {
+ //new OpenVPNThreadv3(this,mProfile);
+ try {
+ Class cl = Class.forName("Lde/blinkt/openvpn/OpenVPNThreadv3;");
+ return (OpenVPNMangement) cl.getConstructor(OpenVpnService.class,VpnProfile.class).newInstance(this,mProfile);
+ } catch (IllegalArgumentException e) {
+ e.printStackTrace();
+ } catch (InstantiationException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ } catch (InvocationTargetException e) {
+ e.printStackTrace();
+ } catch (NoSuchMethodException e) {
+ e.printStackTrace();
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
@Override
public void onDestroy() {
if (mProcessThread != null) {
- mSocketManager.managmentCommand("signal SIGINT\n");
+ mManagement.stopVPN();
mProcessThread.interrupt();
}
@@ -426,6 +502,10 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac
}
+ public void addRoute(CIDRIP route)
+ {
+ mRoutes.add(route );
+ }
public void addRoute(String dest, String mask) {
CIDRIP route = new CIDRIP(dest, mask);
if(route.len == 32 && !mask.equals("255.255.255.255")) {
@@ -442,6 +522,15 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac
mRoutesv6.add(extra);
}
+ public void setMtu(int mtu) {
+ mMtu=mtu;
+ }
+
+ public void setLocalIP(CIDRIP cdrip)
+ {
+ mLocalIP=cdrip;
+ }
+
public void setLocalIP(String local, String netmask,int mtu, String mode) {
mLocalIP = new CIDRIP(local, netmask);
@@ -451,7 +540,7 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac
// get the netmask as IP
long netint = CIDRIP.getInt(netmask);
if(Math.abs(netint - mLocalIP.getInt()) ==1) {
- if(mode.equals("net30"))
+ if("net30".equals(mode))
mLocalIP.len=30;
else
mLocalIP.len=31;
@@ -469,20 +558,23 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac
public void updateState(String state,String logmessage, int resid) {
// If the process is not running, ignore any state,
// Notification should be invisible in this state
- if(mProcessThread==null)
+ if(mProcessThread==null && !mNotificationalwaysVisible)
return;
// Display byte count only after being connected
- if("BYTECOUNT".equals(state)) {
- if(mDisplayBytecount) {
- showNotification(logmessage,null,true,mConnecttime);
- }
- } else {
+ {
+ int level;
if("CONNECTED".equals(state)) {
mDisplayBytecount = true;
mConnecttime = System.currentTimeMillis();
+ level = LEVEL_CONNECTED;
} else {
+ if ("NONETWORK".equals(state)) {
+ level = LEVEL_OFFLINE;
+ } else {
+ level = LEVEL_NOTCONNECTED;
+ }
mDisplayBytecount = false;
}
@@ -490,12 +582,36 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac
// This also mean we are no longer connected, ignore bytecount messages until next
// CONNECTED
String ticker = getString(resid);
- showNotification(getString(resid) +" " + logmessage,ticker,false,0);
+ showNotification(getString(resid) +" " + logmessage,ticker,false,0, level);
}
}
@Override
+ public void updateByteCount(long in, long out, long diffin, long diffout) {
+ if(mDisplayBytecount) {
+ String netstat = String.format(getString(R.string.statusline_bytecount),
+ humanReadableByteCount(in, false),
+ humanReadableByteCount(diffin, false),
+ humanReadableByteCount(out, false),
+ humanReadableByteCount(diffout, false));
+
+ boolean lowpriority = !mNotificationalwaysVisible;
+ showNotification(netstat,null,lowpriority,mConnecttime, LEVEL_CONNECTED);
+ }
+
+ }
+
+ // From: http://stackoverflow.com/questions/3758606/how-to-convert-byte-size-into-human-readable-format-in-java
+ public static String humanReadableByteCount(long bytes, boolean si) {
+ int unit = si ? 1000 : 1024;
+ if (bytes < unit) return bytes + " B";
+ int exp = (int) (Math.log(bytes) / Math.log(unit));
+ String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp-1) + (si ? "" : "i");
+ return String.format(Locale.getDefault(),"%.1f %sB", bytes / Math.pow(unit, exp), pre);
+ }
+
+ @Override
public boolean handleMessage(Message msg) {
Runnable r = msg.getCallback();
if(r!=null){
@@ -505,4 +621,8 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac
return false;
}
}
+
+ public OpenVPNMangement getManagement() {
+ return mManagement;
+ }
}