diff options
author | Arne Schwabe <arne@rfc2549.org> | 2012-06-20 22:30:53 +0200 |
---|---|---|
committer | Arne Schwabe <arne@rfc2549.org> | 2012-06-20 22:30:53 +0200 |
commit | 47e1a6d2dd8e1416dcf4944c0258e999e7102677 (patch) | |
tree | da2e4a094a3e352ce7a842cba86d29864947c0a2 | |
parent | e8ea1db33db4fb9b4ef360125d2ec95071cd6424 (diff) | |
parent | e9b93deeff850a113870e1b27bde251d266b9d7c (diff) |
merge
-rw-r--r-- | README.txt | 20 | ||||
-rw-r--r-- | proguard.cfg | 40 | ||||
-rw-r--r-- | res/values/strings.xml | 14 | ||||
-rw-r--r-- | res/xml/general_settings.xml | 10 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/LaunchVPN.java | 60 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/LogWindow.java | 7 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/NetworkSateReceiver.java | 1 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/OpenVPN.java | 16 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/OpenVPNThread.java | 2 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/OpenVpnManagementThread.java | 40 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/OpenVpnService.java | 72 | ||||
-rw-r--r-- | todo.txt | 10 |
12 files changed, 175 insertions, 117 deletions
@@ -12,3 +12,23 @@ Do ndk-build in the root directory of the project. Use eclipse with android plugins to build the project. Optional: Copy minivpn from lib/ to assets (if you want your own compiled version) + + + + +Starting a VPN by name from an external app: + +public class StartOpenVPNActivity extends Activity { + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + + final String EXTRA_NAME = "de.blinkt.openvpn.shortcutProfileName"; + + Intent shortcutIntent = new Intent(Intent.ACTION_MAIN); + shortcutIntent.setClassName("de.blinkt.openvpn", "de.blinkt.openvpn.LaunchVPN"); + shortcutIntent.putExtra(EXTRA_NAME,"upb ssl"); + startActivity(shortcutIntent); + } +}
\ No newline at end of file diff --git a/proguard.cfg b/proguard.cfg deleted file mode 100644 index b1cdf17b..00000000 --- a/proguard.cfg +++ /dev/null @@ -1,40 +0,0 @@ --optimizationpasses 5 --dontusemixedcaseclassnames --dontskipnonpubliclibraryclasses --dontpreverify --verbose --optimizations !code/simplification/arithmetic,!field/*,!class/merging/* - --keep public class * extends android.app.Activity --keep public class * extends android.app.Application --keep public class * extends android.app.Service --keep public class * extends android.content.BroadcastReceiver --keep public class * extends android.content.ContentProvider --keep public class * extends android.app.backup.BackupAgentHelper --keep public class * extends android.preference.Preference --keep public class com.android.vending.licensing.ILicensingService - --keepclasseswithmembernames class * { - native <methods>; -} - --keepclasseswithmembers class * { - public <init>(android.content.Context, android.util.AttributeSet); -} - --keepclasseswithmembers class * { - public <init>(android.content.Context, android.util.AttributeSet, int); -} - --keepclassmembers class * extends android.app.Activity { - public void *(android.view.View); -} - --keepclassmembers enum * { - public static **[] values(); - public static ** valueOf(java.lang.String); -} - --keep class * implements android.os.Parcelable { - public static final android.os.Parcelable$Creator *; -} diff --git a/res/values/strings.xml b/res/values/strings.xml index 32e2a2ae..2f827fe5 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -24,6 +24,7 @@ <string name="defaultport" translatable="false">1194</string> <string name="location">Location</string> <string name="cant_read_folder">folder can\'t be read!</string> + <string name="select">Select</string> <string name="cancel">Cancel</string> <string name="no_data">No Data</string> <string name="useLZO">LZO Compression</string> @@ -32,6 +33,7 @@ <string name="client_key_title">Client Certificate Key</string> <string name="client_pkcs12_title">PKCS12 File</string> <string name="ca_title">CA Certificate</string> + <string name="select_certificate">Select</string> <string name="no_certificate">Nothing selected</string> <string name="opevpn_copyright" translatable="false">Copyright © 2002–2010 OpenVPN Technologies, Inc. <sales@openvpn.net>\n @@ -55,7 +57,6 @@ <string name="vpn_list_title">All your precious VPNs</string> <string name="vpn_type">Type</string> <string name="pkcs12pwquery">PKCS12 Password</string> - <string name="select">Select…</string> <string name="file_select">Select…</string> <string name="file_nothing_selected">Nothing Selected</string> <string name="useTLSAuth">Use TLS Authentication</string> @@ -123,7 +124,7 @@ <string name="custom_options_title">Custom Options</string> <string name="edit_vpn">Edit VPN Settings</string> <string name="remove_vpn_query">Remove the VPN Profile %s?</string> - <string name="tun_error_helpful">On some custom ICS images the permission on /dev/tun might be wrong, or the tun module might be missing completely. For CM9 images try the fix ownership option under general settings"</string> + <string name="tun_error_helpful">On some custom ICS images the permission on /dev/tun might be wrong, or the tun module might be missing completely. For CM9 images try the fix ownership option under general settings</string> <string name="tun_open_error">Opening tun interface failed badly.</string> <string name="error">"Error: "</string> <string name="clear">Clear</string> @@ -212,6 +213,11 @@ <string name="netstatus">Network Status: %s</string> <string name="extracahint">The CA cert is usually returned from the Android Keystore. Specify a separate certificate if you get certificate verification errors.</string> <string name="select_file">Select</string> - <string name="keychain_nocacert">No CA Certificate returned while reading from Android keystore. Authentication will probably fail.</string> - + + <string name="keychain_nocacert">No CA Certificate returned while reading from Android keystore. Auhtentication will probably fail.</string> + <string name="show_log_summary">Shows the log window on connect. The log window can always be accessed from the notification status.</string> + <string name="show_log_window">Show log window</string> + <string name="keppstatus_summary">Keep the notification displayed after the connection is established to show traffic statistics.</string> + <string name="keepstatus">Show Traffic Statistics</string> </resources> + diff --git a/res/xml/general_settings.xml b/res/xml/general_settings.xml index 74c8965f..2da80cc6 100644 --- a/res/xml/general_settings.xml +++ b/res/xml/general_settings.xml @@ -11,5 +11,15 @@ android:key="useCM9Fix" android:summary="@string/owner_fix_summary" android:title="@string/owner_fix" /> + <CheckBoxPreference + android:defaultValue="false" + android:key="showlogwindow" + android:summary="@string/show_log_summary" + android:title="@string/show_log_window" /> + <CheckBoxPreference + android:defaultValue="false" + android:key="statusafterconnect" + android:summary="@string/keppstatus_summary" + android:title="@string/keepstatus" /> </PreferenceScreen>
\ No newline at end of file diff --git a/src/de/blinkt/openvpn/LaunchVPN.java b/src/de/blinkt/openvpn/LaunchVPN.java index e76057d7..1c873f22 100644 --- a/src/de/blinkt/openvpn/LaunchVPN.java +++ b/src/de/blinkt/openvpn/LaunchVPN.java @@ -44,7 +44,6 @@ import android.widget.ArrayAdapter; import android.widget.EditText; import android.widget.ListView; import android.widget.TextView; -import android.widget.Toast; /** * This Activity actually handles two stages of a launcher shortcut's life cycle. @@ -80,11 +79,11 @@ public class LaunchVPN extends ListActivity implements OnItemClickListener { private ProfileManager mPM; private VpnProfile mSelectedProfile; - - + + private boolean mCmfixed=false; static boolean minivpnwritten=false; - + @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); @@ -92,7 +91,7 @@ public class LaunchVPN extends ListActivity implements OnItemClickListener { mPM =ProfileManager.getInstance(this); } - + @Override protected void onStart() { super.onStart(); @@ -100,6 +99,7 @@ public class LaunchVPN extends ListActivity implements OnItemClickListener { final Intent intent = getIntent(); final String action = intent.getAction(); + // If the intent is a request to create a shortcut, we'll do that and exit if(Intent.ACTION_MAIN.equals(action)) { @@ -110,10 +110,11 @@ public class LaunchVPN extends ListActivity implements OnItemClickListener { VpnProfile profileToConnect = ProfileManager.get(shortcutUUID); if(shortcutName != null && profileToConnect ==null) profileToConnect = ProfileManager.getInstance(this).getProfileByName(shortcutName); - + if(profileToConnect ==null) { - Toast notfound = Toast.makeText(this, R.string.shortcut_profile_notfound, Toast.LENGTH_SHORT); - notfound.show(); + OpenVPN.logError(R.string.shortcut_profile_notfound); + // show Log window to display error + showLogWindow(); finish(); return; } @@ -221,31 +222,31 @@ public class LaunchVPN extends ListActivity implements OnItemClickListener { // } } - + private boolean writeMiniVPN() { File mvpnout = new File(getCacheDir(),"minivpn"); if (mvpnout.exists() && mvpnout.canExecute()) return true; - + if(minivpnwritten) return true; try { InputStream mvpn = getAssets().open("minivpn"); - + FileOutputStream fout = new FileOutputStream(mvpnout); - + byte buf[]= new byte[4096]; - + int lenread = mvpn.read(buf); while(lenread> 0) { fout.write(buf, 0, lenread); lenread = mvpn.read(buf); } fout.close(); - + if(!mvpnout.setExecutable(true)) return false; - + minivpnwritten=true; return true; } catch (IOException e) { @@ -303,26 +304,36 @@ public class LaunchVPN extends ListActivity implements OnItemClickListener { if(needpw !=0) { askForPW(needpw); } else { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); + boolean showlogwindow = prefs.getBoolean("showlogwindow", false); + if(showlogwindow) + showLogWindow(); new startOpenVpnThread().start(); } - } else if (resultCode == Activity.RESULT_CANCELED) { // User does not want us to start, so we just vanish finish(); } } } + void showLogWindow() { + + Intent startLW = new Intent(getBaseContext(),LogWindow.class); + startLW.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); + startActivity(startLW); + + } void showConfigErrorDialog(int vpnok) { AlertDialog.Builder d = new AlertDialog.Builder(this); d.setTitle(R.string.config_error_found); d.setMessage(vpnok); d.setPositiveButton(android.R.string.ok, new OnClickListener() { - + @Override public void onClick(DialogInterface dialog, int which) { finish(); - + } }); d.show(); @@ -339,7 +350,7 @@ public class LaunchVPN extends ListActivity implements OnItemClickListener { // Check if we want to fix /dev/tun SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); boolean usecm9fix = prefs.getBoolean("useCM9Fix", false); - + if(usecm9fix && !mCmfixed ) { ProcessBuilder pb = new ProcessBuilder(new String[] {"su","-c","chown system /dev/tun"}); try { @@ -353,8 +364,8 @@ public class LaunchVPN extends ListActivity implements OnItemClickListener { e.printStackTrace(); } } - - + + if (intent != null) { // Start the query @@ -363,7 +374,8 @@ public class LaunchVPN extends ListActivity implements OnItemClickListener { } catch (ActivityNotFoundException ane) { // Shame on you Sony! At least one user reported that // an official Sony Xperia Arc S image triggers this exception - Toast.makeText(this, R.string.no_vpn_support_image, Toast.LENGTH_LONG).show(); + OpenVPN.logError(R.string.no_vpn_support_image); + showLogWindow(); } } else { onActivityResult(START_VPN_PROFILE, Activity.RESULT_OK, null); @@ -379,10 +391,6 @@ public class LaunchVPN extends ListActivity implements OnItemClickListener { } void startOpenVpn() { - Intent startLW = new Intent(getBaseContext(),LogWindow.class); - startLW.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); - startActivity(startLW); - if(!writeMiniVPN()) { OpenVPN.logMessage(0, "", "Error writing minivpn binary"); return; diff --git a/src/de/blinkt/openvpn/LogWindow.java b/src/de/blinkt/openvpn/LogWindow.java index 6060e7ad..ae5277cd 100644 --- a/src/de/blinkt/openvpn/LogWindow.java +++ b/src/de/blinkt/openvpn/LogWindow.java @@ -271,12 +271,15 @@ public class LogWindow extends ListActivity implements StateListener { } @Override - public void updateState(final String logmessage) { + public void updateState(final String status,final String logmessage) { runOnUiThread(new Runnable() { @Override public void run() { - mSpeedView.setText(logmessage); + String prefix=status+ ":"; + if (status.equals("BYTECOUNT") || status.equals("NOPROCESS") ) + prefix=""; + mSpeedView.setText(prefix + logmessage); } }); diff --git a/src/de/blinkt/openvpn/NetworkSateReceiver.java b/src/de/blinkt/openvpn/NetworkSateReceiver.java index a8d69896..0758cf3a 100644 --- a/src/de/blinkt/openvpn/NetworkSateReceiver.java +++ b/src/de/blinkt/openvpn/NetworkSateReceiver.java @@ -26,7 +26,6 @@ public class NetworkSateReceiver extends BroadcastReceiver { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean sendusr1 = prefs.getBoolean("netchangereconnect", true);
-
String netstatestring;
if(networkInfo==null)
netstatestring = "not connected";
diff --git a/src/de/blinkt/openvpn/OpenVPN.java b/src/de/blinkt/openvpn/OpenVPN.java index b09eb60e..c23ee56d 100644 --- a/src/de/blinkt/openvpn/OpenVPN.java +++ b/src/de/blinkt/openvpn/OpenVPN.java @@ -41,6 +41,12 @@ public class OpenVPN { } + public LogItem(int loglevel, int ressourceId) { + mRessourceId =ressourceId; + mLevel = loglevel; + } + + String getString(Context c) { if(mMessage !=null) { return mMessage; @@ -73,7 +79,7 @@ public class OpenVPN { } public interface StateListener { - void updateState(String logmessage); + void updateState(String state, String logmessage); } synchronized static void logMessage(int level,String prefix, String message) @@ -126,9 +132,9 @@ public class OpenVPN { } - public static void updateStateString(String msg) { + public static void updateStateString(String state, String msg) { for (StateListener sl : stateListener) { - sl.updateState(msg); + sl.updateState(state,msg); } } @@ -155,6 +161,10 @@ public class OpenVPN { } + public static void logError(int ressourceId) { + newlogItem(new LogItem(LogItem.ERROR, ressourceId)); + } + } diff --git a/src/de/blinkt/openvpn/OpenVPNThread.java b/src/de/blinkt/openvpn/OpenVPNThread.java index fdb0ac02..22a08763 100644 --- a/src/de/blinkt/openvpn/OpenVPNThread.java +++ b/src/de/blinkt/openvpn/OpenVPNThread.java @@ -41,7 +41,7 @@ public class OpenVPNThread implements Runnable { //mInterface = null;
- OpenVPN.updateStateString("No process running");
+ OpenVPN.updateStateString("NOPROCESS","No process running");
// Not a good place to do it, but will do
OpenVPN.logBuilderConfig(null);
Log.i(TAG, "Exiting");
diff --git a/src/de/blinkt/openvpn/OpenVpnManagementThread.java b/src/de/blinkt/openvpn/OpenVpnManagementThread.java index 012e0923..f23d9d9b 100644 --- a/src/de/blinkt/openvpn/OpenVpnManagementThread.java +++ b/src/de/blinkt/openvpn/OpenVpnManagementThread.java @@ -21,7 +21,8 @@ public class OpenVpnManagementThread implements Runnable { private LinkedList<FileDescriptor> mFDList=new LinkedList<FileDescriptor>();
private int mBytecountinterval=2;
private long mLastIn=0;
- private long mLastOut=0;
+ private long mLastOut=0;
+ private String mCurrentstate;
private static Vector<OpenVpnManagementThread> active=new Vector<OpenVpnManagementThread>();
@@ -185,8 +186,9 @@ public class OpenVpnManagementThread implements Runnable { }
private void processState(String argument) {
- String[] args = argument.split(",",2);
- OpenVPN.updateStateString(args[1]);
+ String[] args = argument.split(",",3);
+ mCurrentstate = args[1];
+ OpenVPN.updateStateString(mCurrentstate,args[2]);
}
@@ -195,32 +197,32 @@ public class OpenVpnManagementThread implements Runnable { int comma = argument.indexOf(',');
long in = Long.parseLong(argument.substring(0, comma));
long out = Long.parseLong(argument.substring(comma+1));
-
+
long diffin = in - mLastIn;
long diffout = out - mLastOut;
-
+
mLastIn=in;
mLastOut=out;
-
- String netstat = String.format("In: %8s, %8s/s Out %8s, %8s/s ",
+
+ String netstat = String.format("In: %8s, %8s/s Out %8s, %8s/s",
humanReadableByteCount(in, false),
humanReadableByteCount(diffin, false),
humanReadableByteCount(out, false),
humanReadableByteCount(diffout, false));
- OpenVPN.updateStateString(netstat);
-
-
+ OpenVPN.updateStateString("BYTECOUNT",netstat);
+
+
}
// 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("%.1f %sB", bytes / Math.pow(unit, exp), pre);
+ 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("%.1f %sB", bytes / Math.pow(unit, exp), pre);
}
-
+
private void processNeedCommand(String argument) {
int p1 =argument.indexOf('\'');
int p2 = argument.indexOf('\'',p1+1);
@@ -328,10 +330,10 @@ public class OpenVpnManagementThread implements Runnable { private void processPWCommand(String argument) {
//argument has the form Need 'Private Key' password
-
+
String needed;
try{
-
+
int p1 = argument.indexOf('\'');
int p2 = argument.indexOf('\'',p1+1);
needed = argument.substring(p1+1, p2);
@@ -384,7 +386,7 @@ public class OpenVpnManagementThread implements Runnable { public void reconnect() {
managmentCommand("signal SIGUSR1\n");
-
+
}
}
diff --git a/src/de/blinkt/openvpn/OpenVpnService.java b/src/de/blinkt/openvpn/OpenVpnService.java index 8c172115..fd0b4f2a 100644 --- a/src/de/blinkt/openvpn/OpenVpnService.java +++ b/src/de/blinkt/openvpn/OpenVpnService.java @@ -19,19 +19,24 @@ package de.blinkt.openvpn; import java.io.IOException; import java.util.Vector; +import de.blinkt.openvpn.OpenVPN.StateListener; + import android.app.Notification; +import android.app.Notification.Builder; import android.app.NotificationManager; 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.LocalSocket; import android.net.LocalSocketAddress; import android.net.VpnService; import android.os.ParcelFileDescriptor; +import android.preference.PreferenceManager; -public class OpenVpnService extends VpnService { +public class OpenVpnService extends VpnService implements StateListener { private Thread mServiceThread; private Vector<String> mDnslist=new Vector<String>(); @@ -54,7 +59,9 @@ public class OpenVpnService extends VpnService { private NetworkSateReceiver mNetworkStateReceiver; - private static final int HELLO_ID = 1; + private boolean mDisplayBytecount=false; + + private static final int OPENVPN_STATUS = 1; @Override public void onRevoke() { @@ -63,24 +70,39 @@ public class OpenVpnService extends VpnService { stopSelf(); }; - private void showNotification() { + private void hideNotification() { + String ns = Context.NOTIFICATION_SERVICE; + NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns); + mNotificationManager.cancel(OPENVPN_STATUS); + + } + private void showNotification(String msg, String tickerText) { String ns = Context.NOTIFICATION_SERVICE; NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns); int icon = R.drawable.icon; - CharSequence tickerText = "Hello"; long when = System.currentTimeMillis(); + + android.app.Notification.Builder nbuilder = new Notification.Builder(this); + + nbuilder.setContentTitle("OpenVPN - " + mProfile.mName); + nbuilder.setContentText(msg); + nbuilder.setOnlyAlertOnce(true); + nbuilder.setOngoing(true); + nbuilder.setContentIntent(getLogPendingIntent()); + nbuilder.setSmallIcon(icon); + nbuilder.setWhen(when); + + if(tickerText!=null) + nbuilder.setTicker(tickerText); - mNotification = new Notification(icon, tickerText, when); + mNotification = nbuilder.getNotification(); - Context context = getApplicationContext(); - CharSequence contentTitle = "My notification"; - CharSequence contentText = "Hello World!"; - mNotification.setLatestEventInfo(context, contentTitle, contentText, getLogPendingIntent()); + - mNotificationManager.notify(HELLO_ID, mNotification); + mNotificationManager.notify(OPENVPN_STATUS, mNotification); } @@ -135,7 +157,7 @@ public class OpenVpnService extends VpnService { String profileUUID = intent.getStringExtra(prefix + ".profileUUID"); mProfile = ProfileManager.get(profileUUID); - //showNotification(); + OpenVPN.addSpeedListener(this); // Stop the previous session by interrupting the thread. if(OpenVpnManagementThread.stopOpenVPN()){ @@ -357,4 +379,32 @@ public class OpenVpnService extends VpnService { mLocalIPv6 = ipv6addr; } + @Override + public void updateState(String state,String logmessage) { + if("NOPROCESS".equals(state)) { + hideNotification(); + mDisplayBytecount=false; + return; + } + + if("CONNECTED".equals(state)) { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); + mDisplayBytecount = prefs.getBoolean("statusafterconnect", false); + if(!mDisplayBytecount) { + hideNotification(); + return; + } + } + + if("BYTECOUNT".equals(state)) { + if(mDisplayBytecount) { + showNotification(logmessage,null); + } + } else { + // Other notifications are shown + String ticker = state.toLowerCase(); + showNotification(state +" " + logmessage,ticker); + } + } + } @@ -9,16 +9,10 @@ Ideas: - implement general settings dialog - encryption of profiles - Speed/Transfered in notification bar (byte counter of management) - - Kick openvpn on network state change (Wifi <-> GPRS/EDGE/UMTS) - - rework logging system (first step: rename OpenVPN class to samething sensible) - - map SIGUSR1 to SIGINT - add a put this certificate into file obscure option -- adding a profile should bring up editing the profile instantly - - Bugfixes: - startpath file explorer @@ -38,7 +32,3 @@ Tap support: - implement arp, possible the most difficult task ... - need to chose right mac of receiver -Requested by users: -auth -mtu-link - |