summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArne Schwabe <arne@rfc2549.org>2012-06-18 00:27:03 +0200
committerArne Schwabe <arne@rfc2549.org>2012-06-18 00:27:03 +0200
commit06917978c727df00627a5b831526def8d613a280 (patch)
treeee911f69986219b09cb32b0cd06fde74c3996351
parent10d1fa59f73ed62990cbc71028fbbb94a8aaa2a5 (diff)
Add a status message which shows the status of the connecting/connected VPN
-rw-r--r--proguard.cfg40
-rw-r--r--res/values/strings.xml13
-rw-r--r--res/xml/general_settings.xml10
-rw-r--r--src/de/blinkt/openvpn/LaunchVPN.java60
-rw-r--r--src/de/blinkt/openvpn/LogWindow.java4
-rw-r--r--src/de/blinkt/openvpn/NetworkSateReceiver.java1
-rw-r--r--src/de/blinkt/openvpn/OpenVPN.java16
-rw-r--r--src/de/blinkt/openvpn/OpenVPNThread.java2
-rw-r--r--src/de/blinkt/openvpn/OpenVpnManagementThread.java40
-rw-r--r--src/de/blinkt/openvpn/OpenVpnService.java68
-rw-r--r--todo.txt10
11 files changed, 147 insertions, 117 deletions
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 f7c9817f..423ad066 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. &lt;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>
@@ -212,6 +213,10 @@
<string name="netstatus">Network Status: %s</string>
<string name="extracahint">The CA cert is usually returned from the Android Keystore. Specify a seperate 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. Auhtentication will probably fail.</string>
-
-</resources>
+ <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> \ No newline at end of file
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..8fadf3ad 100644
--- a/src/de/blinkt/openvpn/LogWindow.java
+++ b/src/de/blinkt/openvpn/LogWindow.java
@@ -271,12 +271,12 @@ 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);
+ mSpeedView.setText(status + " " + 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..a0d7503d 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,36 @@ 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 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);
- mNotification = new Notification(icon, tickerText, when);
+ nbuilder.setContentTitle("OpenVPN - " + mProfile.mName);
+ nbuilder.setContentText(msg);
+ nbuilder.setOnlyAlertOnce(true);
+ nbuilder.setOngoing(true);
+ nbuilder.setContentIntent(getLogPendingIntent());
+ nbuilder.setSmallIcon(icon);
+ nbuilder.setWhen(when);
- Context context = getApplicationContext();
- CharSequence contentTitle = "My notification";
- CharSequence contentText = "Hello World!";
+ mNotification = nbuilder.getNotification();
- mNotification.setLatestEventInfo(context, contentTitle, contentText, getLogPendingIntent());
- mNotificationManager.notify(HELLO_ID, mNotification);
+
+
+ mNotificationManager.notify(OPENVPN_STATUS, mNotification);
}
@@ -135,7 +154,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 +376,31 @@ 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);
+ }
+ } else {
+ // Other notifications are shown
+ showNotification(state +" " + logmessage);
+ }
+ }
+
}
diff --git a/todo.txt b/todo.txt
index bb5135f8..06948a72 100644
--- a/todo.txt
+++ b/todo.txt
@@ -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
-